Spaces:
Running
Running
Download assets/gallery.js from SimWorld-AI/Code4Scene: direct link, hf CLI and curl.
- Browser
- Download file 3.53 kB
-
https://huggingface.co/spaces/SimWorld-AI/Code4Scene/resolve/main/assets/gallery.js
- Command line
-
hf download hf://spaces/SimWorld-AI/Code4Scene/assets/gallery.js
-
curl -L -o gallery.js https://huggingface.co/spaces/SimWorld-AI/Code4Scene/resolve/main/assets/gallery.js
3.53 kB
| // 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 = '<button class="gbox-x" type="button" aria-label="Close">×</button>' | |
| + '<button class="gbox-prev" type="button" aria-label="Previous view">‹</button>' | |
| + '<figure><img alt=""><figcaption class="gbox-cap"></figcaption></figure>' | |
| + '<button class="gbox-next" type="button" aria-label="Next view">›</button>'; | |
| 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); }); | |
| })(); | |