// Text-to-Scene gallery (scripts/t2s_gallery.py): a viewer for the renders, stepping through one agent's four views
// of a scene, and "Full brief" for the scene briefs. Without it, every thumbnail still links to its full render.
(() => {
const links = [...document.querySelectorAll('a.gimg')];
if (links.length) {
const box = document.createElement('div');
box.className = 'gbox'; box.hidden = true;
box.setAttribute('role', 'dialog'); box.setAttribute('aria-modal', 'true'); box.setAttribute('aria-label', 'Render viewer');
box.innerHTML = ''
+ ''
+ '
'
+ '';
document.body.append(box);
const img = box.querySelector('img'), cap = box.querySelector('.gbox-cap'), buttons = [...box.querySelectorAll('button')];
let group = [], i = 0, opener = null;
const show = k => {
i = (k + group.length) % group.length;
const a = group[i];
img.src = a.href; img.alt = a.dataset.caption; cap.textContent = a.dataset.caption;
new Image().src = group[(i + 1) % group.length].href; // the next view, ahead of the click
};
const open = a => {
group = links.filter(x => x.dataset.group === a.dataset.group);
opener = a; show(group.indexOf(a));
box.hidden = false; document.body.style.overflow = 'hidden'; buttons[0].focus();
};
const close = () => {
box.hidden = true; img.removeAttribute('src'); document.body.style.overflow = '';
if (opener) opener.focus();
};
links.forEach(a => a.addEventListener('click', ev => {
if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey || ev.button) return;
ev.preventDefault(); open(a);
}));
buttons[0].addEventListener('click', close);
buttons[1].addEventListener('click', () => show(i - 1));
buttons[2].addEventListener('click', () => show(i + 1));
box.addEventListener('click', ev => { if (ev.target === box) close(); });
document.addEventListener('keydown', ev => {
if (box.hidden) return;
if (ev.key === 'Escape') close();
else if (ev.key === 'ArrowLeft') show(i - 1);
else if (ev.key === 'ArrowRight') show(i + 1);
else if (ev.key === 'Tab') { // keep focus on the viewer's three buttons
const k = buttons.indexOf(document.activeElement);
ev.preventDefault(); buttons[(k + (ev.shiftKey ? -1 : 1) + buttons.length) % buttons.length].focus();
}
});
}
// briefs: two lines, and a "Full brief" button where that hides text
const fit = () => document.querySelectorAll('.gal-brief').forEach(p => {
let b = p.nextElementSibling;
if (!b || !b.classList.contains('gal-brief-btn')) {
b = Object.assign(document.createElement('button'), {type: 'button', className: 'gal-brief-btn'});
b.addEventListener('click', () => { b.textContent = p.classList.toggle('open') ? 'Less' : 'Full brief'; });
p.after(b);
}
if (p.classList.contains('open')) return;
b.textContent = 'Full brief';
b.hidden = p.scrollHeight <= p.clientHeight + 1;
});
(document.fonts ? document.fonts.ready : Promise.resolve()).then(fit);
let t;
addEventListener('resize', () => { clearTimeout(t); t = setTimeout(fit, 150); });
})();