import { core } from "../core.js";
import { isValidUrl } from "../utils.js";
function getGalleryConfig() {
return core.CONFIG?.viewer?.gallery || {};
}
function getGalleryHost(Viewer, mainElement) {
return (
Viewer.fileElement?.[0] ||
mainElement ||
Viewer.container ||
core.container ||
null
);
}
function removeExistingGalleryDom() {
document.getElementById("image-list")?.remove();
document.getElementById("modalGallery")?.remove();
}
function createPlaceholderSvgDataUrl(index, label = "") {
const palette = [
["#1f3c88", "#6da3ff"],
["#0f766e", "#6ee7b7"],
["#9a3412", "#fdba74"],
["#5b21b6", "#c4b5fd"],
];
const [start, end] = palette[index % palette.length];
const title = label || `Preview ${index + 1}`;
const svg = `
`.trim();
return `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(svg)}`;
}
function getConfiguredTestImages() {
const gallery = getGalleryConfig();
const configuredImages = Array.isArray(gallery.testImages) ? gallery.testImages : [];
const normalizedImages = configuredImages.map((entry, index) => {
if (typeof entry === "string") {
const src = normalizeGalleryUrl(entry);
return src ? { src, alt: `Preview ${index + 1}` } : null;
}
if (entry && typeof entry === "object") {
const src = normalizeGalleryUrl(entry.src || entry.url || "");
if (!src) return null;
return {
src,
alt: String(entry.alt || entry.label || `Preview ${index + 1}`),
};
}
return null;
}).filter(Boolean);
if (normalizedImages.length > 0) {
return normalizedImages;
}
return [];
}
function createDefaultTestImages() {
return Array.from({ length: 9 }, (_unused, index) => ({
src: createPlaceholderSvgDataUrl(index, `Preview ${index + 1}`),
alt: `Preview ${index + 1}`,
}));
}
function createFakeGalleryElements(testImages) {
return testImages.map((entry) => {
const wrapper = document.createElement("div");
wrapper.className = "field__item";
wrapper.innerHTML =
`
`;
return wrapper;
});
}
function prepareGalleryImages(Viewer, imageElementsChildren) {
imageElementsChildren = imageElementsChildren.filter(function (_image) {
if (!(_image instanceof Element)) return false;
let rawUrl = "";
const img = _image.querySelector("img");
const link = _image.querySelector("a");
if (img && img.getAttribute("src")) {
rawUrl = img.getAttribute("src");
} else if (link && link.getAttribute("href")) {
rawUrl = link.getAttribute("href");
} else {
rawUrl = (_image.textContent || _image.innerHTML || "").trim();
}
const normalized = normalizeGalleryUrl(rawUrl);
if (!isValidUrl(normalized)) {
return false;
}
_image.innerHTML = normalized;
return !!img;
});
imageElementsChildren.forEach(function (imgLink) {
imgLink.innerHTML =
'
';
});
return imageElementsChildren;
}
function normalizeGalleryUrl(rawUrl) {
if (!rawUrl || typeof rawUrl !== "string") {
return "";
}
let url = rawUrl.trim();
if (url === "") {
return "";
}
if (url.startsWith("public://")) {
url = "/sites/default/files/" + url.substring("public://".length);
} else if (url.startsWith("sites/default/files/")) {
url = "/" + url;
}
const base = (core.CONFIG?.mainUrl || window.location.origin || "").replace(/\/+$/, "");
try {
const parsed = new URL(url, window.location.origin);
const host = parsed.host || "";
const path = parsed.pathname || "";
const normalizedHost = host.toLowerCase();
const hasBadHost = host.includes("_") || normalizedHost === "default" || normalizedHost === "dfg_3dviewer";
if (path.startsWith("/sites/default/files/")) {
if (hasBadHost) {
return `${base}${path}`;
}
if (parsed.protocol === "http:" || parsed.protocol === "https:") {
return parsed.href;
}
return `${base}${path}`;
}
return parsed.href;
} catch (_error) {
if (url.startsWith("/sites/default/files/")) {
return `${base}${url}`;
}
return url;
}
}
function handleImages(Viewer, mainElement, imageElements, imageElementsChildren) {
if (imageElementsChildren === undefined) {
imageElementsChildren = imageElements;
}
removeExistingGalleryDom();
var imageList = document.createElement("div");
imageList.setAttribute("id", "image-list");
imageList.style.display = "flex";
imageList.style.flexWrap = "wrap";
imageList.style.gap = "16px";
imageList.style.alignItems = "center";
var modalGallery = document.createElement("div");
var modalImage = document.createElement("img");
modalImage.setAttribute("class", "modalImage");
modalImage.style.transform = "scale(0.95)";
Viewer.bindEventListener(modalGallery, "wheel", function (e) {
e.preventDefault();
e.stopPropagation();
if (e.deltaY > 0 && Viewer.zoomImage > 0.15) {
modalImage.style.transform = `scale(${(Viewer.zoomImage -= Viewer.ZOOM_SPEED_IMAGE)})`;
} else if (e.deltaY < 0 && Viewer.zoomImage < 5) {
modalImage.style.transform = `scale(${(Viewer.zoomImage += Viewer.ZOOM_SPEED_IMAGE)})`;
}
return false;
});
var modalClose = document.createElement("span");
modalGallery.setAttribute("id", "modalGallery");
modalGallery.setAttribute("class", "modalGallery");
modalClose.setAttribute("class", "closeGallery");
modalClose.setAttribute("title", "Close");
modalClose.innerHTML = "×";
modalClose.onclick = function () {
modalGallery.classList.remove("is-open");
};
Viewer.bindEventListener(document, "click", function (event) {
if (
!modalGallery.contains(event.target) &&
!imageList.contains(event.target)
) {
modalGallery.classList.remove("is-open");
Viewer.zoomImage = 1.5;
modalImage.style.transform = "scale(1.5)";
}
});
modalGallery.appendChild(modalImage);
modalGallery.appendChild(modalClose);
for (let i = 0; imageElementsChildren.length - i >= 0; i++) {
if (
imageElementsChildren[i] !== undefined &&
imageElementsChildren[i].innerHTML !== undefined
) {
var imgList = imageElementsChildren[i].getElementsByTagName("a");
for (let j = 0; j < imgList.length; j++) {
imgList[j].setAttribute("href", "#");
imgList[j].setAttribute("src", imgList[j].firstChild.src);
imgList[j].setAttribute("class", "image-list-item");
}
imgList = imageElementsChildren[i].getElementsByTagName("img");
if (imgList.length == 1) {
imgList[0].style.maxWidth = "fit-content";
imgList[0].style.maxHeight = "180px";
}
for (let j = 0; j < imgList.length; j++) {
imgList[j].onclick = function () {
modalGallery.classList.add("is-open");
imageList.style.zIndex = 0;
imageList.style.display = "hidden";
modalImage.src = this.src;
};
}
if (imageElementsChildren[i] instanceof HTMLElement) {
imageElementsChildren[i].style.display = "block";
}
imageList.appendChild(imageElementsChildren[i]);
}
}
if (
imageList &&
imageList.childNodes.length > 0 &&
getGalleryHost(Viewer, mainElement)
) {
const galleryHost = getGalleryHost(Viewer, mainElement);
galleryHost.insertAdjacentElement("beforebegin", modalGallery);
galleryHost.insertAdjacentElement("beforebegin", imageList);
}
}
export function buildThumbnailGallery(Viewer) {
const gallery = getGalleryConfig();
var mainElement = gallery.container
? document.getElementById(gallery.container)
: null;
var imageElements;
if (gallery.imageClass !== "") {
imageElements = document.getElementsByClassName(
gallery.imageClass
);
if (imageElements.length === 0) {
const fallbackFields = document.querySelectorAll(
".field--type-image"
);
if (fallbackFields.length > 0) {
imageElements = fallbackFields;
console.warn(
"Gallery imageClass not found, falling back to .field--type-image."
);
}
}
if (imageElements.length > 0) {
var galleryLabel = document.getElementsByClassName("field__label");
if (galleryLabel !== undefined && galleryLabel.length > 0) {
galleryLabel[0].innerText = "";
}
}
} else if (gallery.imageId !== "") {
imageElements = document.getElementById(gallery.imageId);
}
if (imageElements != null) {
if (imageElements.length > 0) {
if (imageElements[0].innerHTML !== undefined) {
let imagesList = Array.from(
imageElements[0].getElementsByClassName("field__items")[0]
.childNodes
);
imagesList = prepareGalleryImages(Viewer, imagesList);
imageElements[0].classList.add("field--label-hidden");
//imageElements[0].classList.add("field__items");
handleImages(Viewer, mainElement, imagesList, imagesList);
} else {
handleImages(Viewer, mainElement, imageElements);
}
} else if (
imageElements.childNodes !== undefined &&
imageElements.childNodes.length > 0
) {
if (
typeof imageElements.childNodes[0].innerHTML == "string" ||
typeof imageElements.childNodes[1].innerHTML == "string"
) {
let imagesList = Array.from(imageElements.childNodes);
imagesList = prepareGalleryImages(Viewer, imagesList);
imageElements.classList.add("field--type-image");
imageElements.classList.add("field--label-hidden");
//imageElements.classList.add("field__items");
handleImages(Viewer, mainElement, imagesList, imageElements);
} else {
handleImages(Viewer, mainElement, imageElements);
}
}
}
if (core.CONFIG?.viewer?.gallery?.buildFake === true) {
const testImages = getConfiguredTestImages();
const fallbackImages = testImages.length > 0 ? testImages : createDefaultTestImages();
if (gallery.build === true) {
const fakeImages = createFakeGalleryElements(fallbackImages);
handleImages(Viewer, mainElement, fakeImages, fakeImages);
console.log("Built fallback thumbnail gallery for local testing");
return;
}
}
console.log("No gallery source found");
}