OK, so, I’m trying to add a custom EXIF field ("Artist") to the lightbox caption in X3 Gallery, so that it displays below the usual EXIF data (Model, Aperture, ISO, etc.) in the overlay.
What I’ve achieved so far:
- I’ve created a working config/exif-data.php endpoint that returns EXIF data from images, including IFD0.Artist, as JSON:
}
"artist": "Richard Dvorak",
"copyright": ":copyright:2006 by Richard Dvorak"
}
- I successfully append "Foto: Richard Dvorak" inside the .popup-exif-caption element during the first image load using a MutationObserver.
The problem:
- On swiping to the next image in the PhotoSwipe lightbox, the EXIF field is not displayed anymore.
- I tried using
x3_photoSwipeLoaded and
pswp.listen('afterChange', ...), but the DOM is either not updated yet or the target
.popup-exif-caption element is missing at that point.
- I also tried combining
afterChangewith a
setTimeout() or
setInterval() waiting for the DOM to be ready — but this is unreliable and introduces flickering or duplicates.
My question:
What is the correct or recommended way to reliably inject a custom field (e.g. from EXIF) into the .popup-exif-caption block every time the lightbox image changes?
Code sample (current approach that fails on swipe):
document.addEventListener("x3_photoSwipeLoaded", function (e) {
const pswp = e.detail;
let lastImgPath = '';
pswp.listen('afterChange', function () {
const curr = pswp.currItem;
if (!curr?.src) return;
const imgPath = curr.src.split('/content/')[1];
if (!imgPath || imgPath === lastImgPath) return;
lastImgPath = imgPath;
// try to wait for .popup-exif-caption to exist
const interval = setInterval(() => {
const exifBox = document.querySelector('.popup-exif-caption');
if (exifBox) {
clearInterval(interval);
// Clean previous entries
exifBox.querySelectorAll('.popup-exif-artist').forEach(el => el.remove());
fetch('/config/exif-data.php?img=' + encodeURIComponent(imgPath))
.then(res => res.json())
.then(data => {
if (!data.artist) return;
const br = document.createElement('br');
const el = document.createElement('span');
el.className = 'popup-exif-el popup-exif-artist';
el.innerText = 'Foto: ' + data.artist;
exifBox.appendChild(br);
exifBox.appendChild(el);
});
}
}, 50);
});
});
Goal:
I would like to cleanly inject one additional line like:
<span class="popup-exif-el popup-exif-artist">Foto: Richard Dvorak</span>
…under the other EXIF entries, on every image, once and reliably – without relying on setInterval() hacks.
Any insight into a better hook or lifecycle trigger inside X3 that ensures .popup-exif-caption is in place after image change would be much appreciated!
Thanks in advance,
Richard