Spaces:
Running
Running
Download static/embed.js from surogate/doodle-decoder: direct link, hf CLI and curl.
- Browser
- Download file 2.5 kB
-
https://huggingface.co/spaces/surogate/doodle-decoder/resolve/main/static/embed.js
- Command line
-
hf download hf://spaces/surogate/doodle-decoder/static/embed.js
-
curl -L -o embed.js https://huggingface.co/spaces/surogate/doodle-decoder/resolve/main/static/embed.js
2.5 kB
| /* Rune Labs: inside surogate.ai a demo drops its own header (the page row already names it) and | |
| reports its height, so the page sizes the frame to fit and nothing scrolls inside it. | |
| The height is the bottom of main's children, not of main itself: Gradio stretches <main> to fill | |
| the frame, so measuring it would grow the frame, which grows main, forever. | |
| surogate.ai asks for this with ?embed=surogate. Being in a frame is not enough: huggingface.co | |
| shows every Space in one too, and there the header and footer should stay. */ | |
| (() => { | |
| if (window.self === window.top || !new URLSearchParams(location.search).has("embed")) return; | |
| document.documentElement.classList.add("rune-embedded"); | |
| let last = 0; | |
| const contentBottom = (main) => { | |
| let bottom = 0; | |
| for (const child of main.children) bottom = Math.max(bottom, child.getBoundingClientRect().bottom); | |
| return bottom + window.scrollY + parseFloat(getComputedStyle(main).paddingBottom || "0"); | |
| }; | |
| const send = () => { | |
| const main = document.querySelector("main"); | |
| if (!main) return; | |
| const height = Math.ceil(contentBottom(main) + 28); | |
| if (Math.abs(height - last) < 2) return; | |
| last = height; | |
| window.parent.postMessage({ type: "rune-labs:height", height }, "*"); | |
| }; | |
| // Gradio renders on the server, then replaces <main> when the browser takes over, and components keep | |
| // filling in after that. So watch the whole body, and let each measurement find the <main> of the moment. | |
| let queued = false; | |
| const schedule = () => { | |
| if (queued) return; | |
| queued = true; | |
| requestAnimationFrame(() => { queued = false; send(); }); | |
| }; | |
| const sizes = new ResizeObserver(schedule); | |
| const start = () => { | |
| new MutationObserver(() => { | |
| const main = document.querySelector("main"); | |
| if (main) for (const child of main.children) sizes.observe(child); | |
| schedule(); | |
| }).observe(document.body, { childList: true, subtree: true, attributes: true, characterData: true }); | |
| addEventListener("load", schedule); | |
| schedule(); | |
| }; | |
| // One "used" note on the first real interaction, so the page can tell a demo opened from a demo tried. | |
| const used = () => window.parent.postMessage({ type: "rune-labs:used" }, "*"); | |
| addEventListener("pointerdown", used, { once: true, capture: true }); | |
| addEventListener("keydown", used, { once: true, capture: true }); | |
| if (document.readyState === "loading") addEventListener("DOMContentLoaded", start); | |
| else start(); | |
| })(); | |