# photonic/3.33/include/js/front-end/src/Core.js

Photonic Gallery &amp; Lightbox for Flickr, SmugMug &amp; Others, version 3.33. 265 lines.

- Page: https://pluginprobe.com/plugins/photonic/3.33/code/include/js/front-end/src/Core.js
- Raw: https://pluginprobe.com/plugins/photonic/3.33/raw/include/js/front-end/src/Core.js
- Modified: 2025-11-09T01:26:42+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/photonic/3.33/code/include/js/front-end/src/Core.js#L10-L20`.

```javascript
import * as Util from "./Util";
import {Tooltip} from "./Components/Tooltip";
import {Prompter} from "./Components/Prompter";

export class Core {
	static lightboxList = [];
	static prompterList = [];

	static lightbox;
	static deep = location.hash;

	static setLightbox = (lb) => this.lightbox = lb;
	static getLightbox = () => this.lightbox;

	static setDeep = (d) => this.deep = d;
	static getDeep = () => this.deep;

	static addToLightboxList = (idx, lightbox) => this.lightboxList[idx] = lightbox;
	static getLightboxList = () => this.lightboxList;

	static showSpinner = () => {
		let loading = document.getElementsByClassName('photonic-loading');
		if (loading.length > 0) {
			loading = loading[0];
		}
		else {
			loading = document.createElement('div');
			loading.className = 'photonic-loading';
		}
		loading.style.display = 'block';
		document.body.appendChild(loading);
	};

	static hideLoading = () => {
		let loading = document.getElementsByClassName('photonic-loading');
		if (loading.length > 0) {
			loading = loading[0];
			loading.style.display = 'none';
		}
	};

	static initializePasswordPrompter = selector => {
		const selectorNoHash = selector.replace(/^#+/g, '');
		const prompter = new Prompter(selectorNoHash);
		prompter.attach();
		this.prompterList[selector] = prompter;
		prompter.show();
	};

	static moveHTML5External = () => {
		let videos = document.getElementById('photonic-html5-external-videos');
		if (!videos) {
			videos = document.createElement('div');
			videos.id = 'photonic-html5-external-videos';
			videos.style.display = 'none';
			document.body.appendChild(videos);
		}

		const current = document.querySelectorAll('.photonic-html5-external');
		if (current) {
			const cLen = current.length;
			for (let c = 0; c < cLen; c++) {
				current[c].classList.remove('photonic-html5-external');
				videos.appendChild(current[c]);
			}
		}
	};

	static blankSlideupTitle = () => {
		document.querySelectorAll('.title-display-slideup-stick, .photonic-slideshow.title-display-slideup-stick').forEach((item) => {
			Array.from(item.getElementsByTagName('a')).forEach(a => {
				a.setAttribute('title', '');
			});
		});
	};

	static showSlideupTitle = () => {
		let titles = document.documentElement.querySelectorAll('.title-display-slideup-stick a .photonic-title');
		const len = titles.length;
		for (let i = 0; i < len; i++) {
			titles[i].style.display = 'block';
		}
	};

	static waitForImages = async (selector) => {
		let images = this.getImagesFromSelector(selector);
		let imageUrlArray = [];
		let anchorArray = [];
		let setDimensions = false;

		if (selector instanceof Element && selector.getAttribute('data-photonic-platform') === 'instagram') {
			setDimensions = true;
		}

		images.forEach(img => {
			imageUrlArray.push(img.getAttribute('src'));
			anchorArray.push(img.parentElement);
		});

		const promiseArray = []; // create an array for promises
		const imageArray = []; // array for the images

		for (const [idx, imageUrl] of imageUrlArray.entries()) {
			promiseArray.push(new Promise(resolve => {
				const img = new Image();
				img.onload = () => {
					if (setDimensions) {
						anchorArray[idx].setAttribute('data-pswp-width', img.naturalWidth);
						anchorArray[idx].setAttribute('data-pswp-height', img.naturalHeight);
					}
					resolve();
				};

				img.src = imageUrl;
				imageArray.push(img);
			}));
		}

		await Promise.all(promiseArray); // wait for all the images to be loaded
		return imageArray;
	};

	static loadSingleImage = async(image) => {
		const promiseArray = [];
		let retImage = null;
		promiseArray.push(new Promise(resolve => {
			const img = new Image();
			img.onload = () => {
				resolve();
			};

			if (image.getAttribute('data-src') !== null) {
				img.src = image.getAttribute('data-src');
			}
			else {
				img.src = image.getAttribute('src'); // Leave the 'src' in just as a backup. E.g. Gallery header images
			}

			retImage = img;
		}));

		await Promise.all(promiseArray);
		return retImage;
	};

	static watchForImages = (selector) => {
		let images = this.getImagesFromSelector(selector);

		const intersectionObserver = new IntersectionObserver((items, observer) => {
			items.forEach((item) => {
				if (item.isIntersecting || item.intersectionRatio > 0) {
					const image = item.target;
					image.closest('a').classList.add('photonic-image-loading');

					this.loadSingleImage(image).then(() => {
						if (image.getAttribute('data-src') !== null && image.getAttribute('data-src') !== '') {
							image.src = image.getAttribute('data-src');
							image.setAttribute('data-src', '');
							image.setAttribute('data-loaded', 'true');
						}

						image.closest('a').classList.remove('photonic-image-loading');
						Util.fadeIn(image);
					});
					observer.unobserve(image);
				}
			});
		});

		images.forEach((image) => {
			intersectionObserver.observe(image);
		});
	};

	static getImagesFromSelector = selector => {
		let images = [];
		if (typeof selector === 'string') {
			document.querySelectorAll(selector).forEach(selection => {
				images = Array.from(selection.getElementsByTagName('img'));
			});
		}
		else if (selector instanceof Element) {
			images = Array.from(selector.getElementsByTagName('img'));
		}
		else if (selector instanceof NodeList) {
			selector.forEach((selection) => {
				images.push(selection.querySelector('img'));
			});
		}
		return images;
	};

	static standardizeTitleWidths = () => {
		const self = this;

		const setWidths = grid => {
			grid.querySelectorAll('.photonic-thumb').forEach(item => {
				let img = item.getElementsByTagName('img');
				if (img != null) {
					img = img[0];
					let title = item.querySelector('.photonic-title-info');
					if (title) {
						title.style.width = img.width + 'px';
					}
				}
			});
		};

		document.querySelectorAll('.photonic-standard-layout.title-display-below, .photonic-standard-layout.title-display-hover-slideup-show, .photonic-standard-layout.title-display-slideup-stick').forEach(grid => {
			if (grid.classList.contains('sizes-present')) {
				self.watchForImages(grid);
				setWidths(grid);
			}
			else {
				self.waitForImages(grid).then(() => {
					setWidths(grid);
				});
			}
		});
	};

	static sanitizeTitles = () => {
		const thumbs = document.querySelectorAll('.photonic-stream a, a.photonic-level-2-thumb');
		thumbs.forEach((thumb) => {
			if (!thumb.parentNode.classList.contains('photonic-header-title')) {
				const title = thumb.getAttribute('title');
				// Not doing a Util.getText, which uses innerHTML, which is susceptible to XSS
				thumb.setAttribute('title', Util.getText(title));
				const dataTitle = thumb.getAttribute('data-title')
				thumb.setAttribute('data-title', Util.HTMLSanitizer.SanitizeHTML(dataTitle));
			}
		});
	};

	static initializeTooltips = () => {
		if (document.querySelector('.title-display-tooltip a, .photonic-slideshow.title-display-tooltip img') != null) {
			Tooltip('[data-photonic-tooltip]', '.photonic-tooltip-container');
		}
	};

	static showRegularGrids = () => {
		document.querySelectorAll('.photonic-standard-layout').forEach(grid => {
			if (grid.classList.contains('sizes-present')) {
				this.watchForImages(grid);
			}
			else {
				this.waitForImages(grid).then(() => {
					grid.querySelectorAll('.photonic-level-1, .photonic-level-2').forEach(item => {
						item.style.display = 'inline-block';
					});
				});
			}
		});
	};

	static executeCommon = () => {
		Core.moveHTML5External();
		Core.blankSlideupTitle();
		Core.standardizeTitleWidths();
		Core.sanitizeTitles();
		Core.initializeTooltips();
		Core.showRegularGrids();
	};
}

```
