Download polish.js from SharpMeow/unroll: direct link, hf CLI and curl.
- Browser
- Download file 4.34 kB
-
https://huggingface.co/spaces/SharpMeow/unroll/resolve/main/polish.js
- Command line
-
hf download hf://spaces/SharpMeow/unroll/polish.js
-
curl -L -o polish.js https://huggingface.co/spaces/SharpMeow/unroll/resolve/main/polish.js
4.34 kB
| // keyboard shortcuts and the help overlay (press ?). Drives the page through its own buttons, | |
| // plus the small camera hooks app.js exposes on window.unrollView. | |
| const $ = (id) => document.getElementById(id); | |
| const KEYS = [ | |
| ['Space', 'Play or pause the unroll'], | |
| ['← →', 'Step the unroll (hold Shift for bigger steps)'], | |
| ['Home / End', 'Jump to rolled / fully unrolled'], | |
| ['1 2 3', 'X-ray, published ink, ink_9um'], | |
| ['R', 'Read the current winding close up'], | |
| ['V', 'Reset the camera view'], | |
| ['U', 'Roll it back up (again to stop)'], | |
| ['T', 'Destroy on or off'], | |
| ['X C B W', 'Destroy tools: Tear, Crush, Burn, Water'], | |
| ['K', 'Crumble the whole scroll to dust (Reset restores it)'], | |
| ['F', 'Full screen'], | |
| ['I', 'About this page'], | |
| ['?', 'Show or hide this help'], | |
| ['Esc', 'Close any panel'], | |
| ]; | |
| const help = document.createElement('section'); | |
| help.id = 'help'; | |
| help.className = 'sheet help'; | |
| help.hidden = true; | |
| help.setAttribute('role', 'dialog'); | |
| help.setAttribute('aria-modal', 'false'); | |
| help.setAttribute('aria-labelledby', 'helpTitle'); | |
| help.innerHTML = `<div class="sheet-head"><div><div class="mono dim">KEYBOARD</div><h2 id="helpTitle">Shortcuts</h2></div> | |
| <button class="icon" id="hClose" aria-label="Close" data-testid="help-close" data-api="panel('help', false)">✕</button></div> | |
| <dl class="keys mono">${KEYS.map(([k, d]) => `<dt>${k.split(' ').map((x) => (x === '/' ? ' / ' : `<kbd>${x}</kbd>`)).join(' ')}</dt><dd>${d}</dd>`).join('')}</dl> | |
| <p class="mono dim small help-foot">Drag to orbit, scroll or pinch to zoom, click a sheet to read it.</p>`; | |
| document.body.appendChild(help); | |
| const tools = document.querySelector('.tools'); | |
| if (tools && !$('btnHelp')) { | |
| const b = document.createElement('button'); | |
| b.className = 'icon'; | |
| b.id = 'btnHelp'; | |
| b.title = 'Keyboard shortcuts (?)'; | |
| b.setAttribute('aria-label', 'Keyboard shortcuts'); | |
| b.textContent = '?'; | |
| b.dataset.testid = 'help'; b.dataset.api = "panel('help')"; | |
| tools.prepend(b); | |
| b.onclick = () => toggleHelp(); | |
| } | |
| let opener = null; | |
| function toggleHelp(force) { | |
| const show = force ?? help.hidden; | |
| if (show) { opener = document.activeElement; help.hidden = false; $('hClose').focus(); } | |
| else if (!help.hidden) { help.hidden = true; opener?.focus?.(); } | |
| } | |
| $('hClose').onclick = () => toggleHelp(false); | |
| const click = (id) => { const el = $(id); if (el && !el.hidden) { el.click(); return true; } return false; }; | |
| const sheetOpen = () => ['focus', 'about', 'openSheet'].some((id) => $(id) && !$(id).hidden); | |
| addEventListener('keydown', (e) => { | |
| if (e.ctrlKey || e.metaKey || e.altKey) return; | |
| if (e.target.closest?.('textarea,select,input:not([type=range])')) return; | |
| const k = e.key; | |
| if (k === '?' || (k === '/' && e.shiftKey)) { e.preventDefault(); toggleHelp(); return; } | |
| if (k === 'Escape') { toggleHelp(false); return; } | |
| if (!help.hidden || sheetOpen()) return; | |
| const range = $('scrubIn'); | |
| const step = (d) => { range.value = Math.max(0, Math.min(1000, +range.value + d)); range.dispatchEvent(new Event('input', { bubbles: true })); range.dispatchEvent(new Event('change', { bubbles: true })); }; | |
| switch (k.toLowerCase()) { | |
| case '1': document.querySelector('[data-layer=xray]')?.click(); break; | |
| case '2': document.querySelector('[data-layer=ink]')?.click(); break; | |
| case '3': document.querySelector('[data-layer=gpu]:not([hidden])')?.click(); break; | |
| case 'r': click('btnRead'); break; | |
| case 'v': window.unrollView?.reset(); break; | |
| case 't': click('btnTear'); break; | |
| case 'c': click('btnCrush'); break; | |
| case 'x': click('toolTear'); break; | |
| case 'b': click('toolBurn'); break; | |
| case 'w': click('toolWater'); break; | |
| case 'k': window.unrollView?.crumble(); break; | |
| case 'u': click('btnRollUp'); break; | |
| case 'i': click('btnInfo'); break; | |
| case 'f': | |
| if (document.fullscreenElement) document.exitFullscreen?.(); | |
| else document.documentElement.requestFullscreen?.().catch(() => {}); | |
| break; | |
| case 'home': e.preventDefault(); step(-1000); break; | |
| case 'end': e.preventDefault(); step(1000); break; | |
| case 'arrowright': case 'arrowleft': | |
| // app.js steps by 1 percent; Shift adds a 5 percent jump | |
| if (e.shiftKey && e.target === document.body) step(k === 'ArrowRight' ? 40 : -40); | |
| break; | |
| default: return; | |
| } | |
| }); | |