Download src/app.js from DarthSoluke/EgoNetDatasetResearch: direct link, hf CLI and curl.
- Browser
- Download file 6.5 kB
-
https://huggingface.co/spaces/DarthSoluke/EgoNetDatasetResearch/resolve/main/src/app.js
- Command line
-
hf download hf://spaces/DarthSoluke/EgoNetDatasetResearch/src/app.js
-
curl -L -o app.js https://huggingface.co/spaces/DarthSoluke/EgoNetDatasetResearch/resolve/main/src/app.js
6.5 kB
| import { readJSON, enhance, icon } from "./ui.js"; | |
| import { | |
| defaults, | |
| catalogView, | |
| bindCatalog, | |
| overviewView, | |
| detailView, | |
| bindDetail, | |
| } from "./catalog.js"; | |
| import { methodsView, somaView, samplesView } from "./reference.js"; | |
| import synthetic from "./synthetic.js?v=history-20261103"; | |
| const app = document.getElementById("app"); | |
| let context; | |
| let currentRoute; | |
| function route() { | |
| const [path, search = ""] = (location.hash.slice(1) || "catalog").split("?"); | |
| const [page, part] = path.split("/"); | |
| return { page, part, params: new URLSearchParams(search) }; | |
| } | |
| function filtersFrom(params) { | |
| const filters = { ...defaults }; | |
| for (const key of [ | |
| "q", | |
| "source", | |
| "method", | |
| "tier", | |
| "status", | |
| "sort", | |
| "route", | |
| ]) { | |
| if (params.has(key)) filters[key] = params.get(key); | |
| } | |
| filters.preview = params.get("preview") === "true"; | |
| if (!["name", "year", "status"].includes(filters.sort)) filters.sort = "name"; | |
| return filters; | |
| } | |
| function render() { | |
| if (!context) return; | |
| synthetic.unmount(); | |
| app.querySelectorAll("video").forEach((video) => video.pause()); | |
| const { page, part, params } = route(); | |
| let active = page, | |
| title, | |
| html; | |
| const datasetId = page.startsWith("ds-") ? page.slice(3) : null; | |
| if (datasetId) { | |
| const tab = ["overview", "annotation", "access", "conversion"].includes( | |
| part, | |
| ) | |
| ? part | |
| : "overview"; | |
| title = context.byId[datasetId]?.name || "未找到数据集"; | |
| active = "catalog"; | |
| html = detailView(datasetId, tab, context); | |
| } else if (page === "synthetic") { | |
| title = "EgoRenderer"; | |
| html = synthetic.render(); | |
| } else if (page === "overview") { | |
| title = "数据分布"; | |
| html = overviewView(context); | |
| } else if (page === "methods") { | |
| title = "标注方法"; | |
| html = methodsView(context); | |
| } else if (page === "soma") { | |
| title = "SOMA转换"; | |
| html = somaView(context); | |
| } else if (page === "samples") { | |
| title = "样例"; | |
| html = samplesView(context); | |
| } else { | |
| title = "数据集"; | |
| active = "catalog"; | |
| html = catalogView(context, filtersFrom(params)); | |
| } | |
| app.innerHTML = html; | |
| document.title = `${title} · EgoNet Datasets`; | |
| document.querySelectorAll("[data-page]").forEach((link) => { | |
| if (link.dataset.page === active) link.setAttribute("aria-current", "page"); | |
| else link.removeAttribute("aria-current"); | |
| }); | |
| if (active === "catalog" && !datasetId) | |
| bindCatalog(context, filtersFrom(params)); | |
| if (datasetId) bindDetail(datasetId, context); | |
| if (page === "synthetic") synthetic.mount(); | |
| enhance(); | |
| document.getElementById("nav-toggle").setAttribute("aria-expanded", "false"); | |
| document.getElementById("site-nav").classList.remove("is-open"); | |
| const heading = app.querySelector("h1"); | |
| if (heading) { | |
| heading.tabIndex = -1; | |
| heading.focus({ preventScroll: true }); | |
| } | |
| const anchor = | |
| part && | |
| (page === "methods" | |
| ? "method-" + part | |
| : page === "soma" | |
| ? "route-" + part | |
| : null); | |
| if (anchor && document.getElementById(anchor)) | |
| document.getElementById(anchor).scrollIntoView(); | |
| else if (currentRoute !== location.hash) window.scrollTo(0, 0); | |
| currentRoute = location.hash; | |
| } | |
| async function boot() { | |
| app.innerHTML = '<div class="loading-state" role="status">读取数据集…</div>'; | |
| try { | |
| const [data, previews, figures, videos, sampling] = await Promise.all([ | |
| readJSON("data/datasets.json"), | |
| ...["previews", "figures", "videos", "sampling"].map((name) => | |
| readJSON(`data/${name}.json`, { optional: true }), | |
| ), | |
| ]); | |
| if ( | |
| !Array.isArray(data.datasets) || | |
| new Set(data.datasets.map((d) => d.id)).size !== data.datasets.length | |
| ) | |
| throw new Error("Dataset schema"); | |
| const by = (items) => | |
| Object.fromEntries( | |
| items.map((value, order) => [value.id, { ...value, order }]), | |
| ); | |
| context = { | |
| data, | |
| previews, | |
| figures, | |
| videos, | |
| sampling, | |
| byId: by(data.datasets), | |
| meta: { | |
| source: by(data.meta.sources), | |
| method: by(data.meta.methods), | |
| tier: by(data.meta.tiers), | |
| status: by(data.meta.statuses), | |
| route: by(data.meta.routes), | |
| }, | |
| }; | |
| document.getElementById("catalog-count").textContent = data.datasets.length; | |
| document.getElementById("data-updated").textContent = data.meta.updated; | |
| render(); | |
| } catch (_) { | |
| app.innerHTML = `<div class="empty-state" role="alert"><i data-lucide="wifi-off" aria-hidden="true"></i><h1>数据集暂不可用</h1>${icon("refresh-cw", "重新加载", 'id="retry-load"')}</div>`; | |
| document.getElementById("retry-load").onclick = boot; | |
| enhance(); | |
| } | |
| } | |
| const themeButton = document.getElementById("theme-toggle"); | |
| let savedTheme; | |
| try { | |
| savedTheme = localStorage.getItem("atlas-theme"); | |
| } catch (_) { | |
| /* Embedded storage may be restricted. */ | |
| } | |
| function setTheme(theme) { | |
| document.documentElement.dataset.theme = theme; | |
| themeButton.title = `切换${theme === "dark" ? "浅色" : "深色"}模式`; | |
| themeButton.setAttribute("aria-label", themeButton.title); | |
| themeButton.innerHTML = `<i data-lucide="${theme === "dark" ? "sun" : "moon"}" aria-hidden="true"></i>`; | |
| enhance(); | |
| } | |
| setTheme( | |
| savedTheme || | |
| (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"), | |
| ); | |
| themeButton.onclick = () => { | |
| const theme = | |
| document.documentElement.dataset.theme === "dark" ? "light" : "dark"; | |
| try { | |
| localStorage.setItem("atlas-theme", theme); | |
| } catch (_) { | |
| /* Keep the current theme without persistence. */ | |
| } | |
| setTheme(theme); | |
| }; | |
| document.getElementById("nav-toggle").onclick = (event) => { | |
| const button = event.currentTarget; | |
| const open = button.getAttribute("aria-expanded") !== "true"; | |
| button.setAttribute("aria-expanded", String(open)); | |
| document.getElementById("site-nav").classList.toggle("is-open", open); | |
| }; | |
| window.addEventListener("hashchange", render); | |
| document.querySelector(".skip-link").onclick = (event) => { | |
| event.preventDefault(); | |
| app.focus(); | |
| app.scrollIntoView(); | |
| }; | |
| document.addEventListener("keydown", (event) => { | |
| if ( | |
| event.key === "Escape" && | |
| document.getElementById("site-nav").classList.contains("is-open") | |
| ) { | |
| document.getElementById("site-nav").classList.remove("is-open"); | |
| document | |
| .getElementById("nav-toggle") | |
| .setAttribute("aria-expanded", "false"); | |
| document.getElementById("nav-toggle").focus(); | |
| } | |
| }); | |
| boot(); | |