Repository navigation
Expand file tree
/
Copy pathapp.js
More file actions
148 lines (144 loc) · 5.6 KB
/
Copy pathapp.js
File metadata and controls
148 lines (144 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import { registerMedia } from "./media-scheduler.js?v=texture-master-20261030-v6-inline1";
import { setMediaUrl } from "./media-delivery.js?v=texture-master-20261030-v6-inline1";
import { initResearch } from "./research.js?v=method-dark-20261031";
import { initMotionGallery } from "./motion-gallery.js?v=texture-master-20261030-v6-inline1";
import { initNavigation } from "./navigation.js?v=texture-master-20261030-v6-inline1";
import { initCinematic } from "./cinematic.js?v=texture-master-20261030-v6-inline1";
import { initPlayground } from "./playground.js?v=texture-master-20261030-v6-inline1";
const $ = (selector) => document.querySelector(selector);
const $$ = (selector) => [...document.querySelectorAll(selector)];
$$('img[data-local-src]').forEach((image) => setMediaUrl(image, "src", image.dataset.localSrc));
const motion = matchMedia("(prefers-reduced-motion: reduce)");
const escape = (value) =>
String(value).replace(
/[&<>"']/g,
(char) =>
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[
char
],
);
let datasets;
// Navigation remains usable before the content finishes loading.
function closeMenu() {
$(".site-header").classList.remove("menu-open");
$("#mobile-menu").setAttribute("aria-expanded", "false");
}
$("#mobile-menu").addEventListener("click", () => {
const open = $(".site-header").classList.toggle("menu-open");
$("#mobile-menu").setAttribute("aria-expanded", String(open));
});
$$(".desktop-nav a").forEach((link) =>
link.addEventListener("click", closeMenu),
);
document.addEventListener("keydown", (event) => {
if (event.key === "Escape") closeMenu();
});
const navObserver = new IntersectionObserver(
(entries) => {
for (const entry of entries)
if (entry.isIntersecting) {
$$(".desktop-nav a").forEach((link) =>
link.classList.toggle("active", link.hash === `#${["in-motion", "navigation"].includes(entry.target.id) ? "simulation" : entry.target.id}`),
);
}
},
{ rootMargin: "-15% 0px -55% 0px" },
);
$$("main section[id]").forEach((section) => navObserver.observe(section));
if (!motion.matches) {
document.documentElement.classList.add("js-motion");
const reveal = new IntersectionObserver(
(entries, observer) => {
entries
.filter((entry) => entry.isIntersecting)
.forEach((entry) => {
entry.target.classList.add("visible");
observer.unobserve(entry.target);
});
},
{ threshold: 0.1 },
);
$$(".reveal").forEach((node) => reveal.observe(node));
}
// Every source is shown directly; the small tag identifies its training stage.
const featured = [
"walking-tours",
"botanic-garden",
"dl3dv",
"citywalker",
"realestate10k",
"rover",
"i2nav-robot",
"ego4d",
];
function orderedDatasets() {
return [...datasets.datasets].sort((a, b) => {
const rank = (item) =>
featured.includes(item.id)
? featured.indexOf(item.id)
: featured.length + datasets.datasets.indexOf(item);
return rank(a) - rank(b);
});
}
// One page-wide scheduler shares bandwidth and decoder capacity.
let datasetMedia = [];
function renderDatasets() {
datasetMedia.forEach((entry) => entry.unregister());
datasetMedia = [];
$("#dataset-grid").innerHTML = orderedDatasets()
.map(
(item) =>
`<article class="dataset-card" data-dataset="${escape(item.id)}"><div class="dataset-card-image"><video data-src="${escape(item.video || "")}" data-poster="${escape(item.image)}" muted loop playsinline preload="none" width="480" height="270" aria-label="${escape(item.name + " dataset video")}"></video></div><div class="dataset-card-label"><h3>${escape(item.name)}</h3><span class="source-group">${item.group === "pretraining" ? "PRETRAIN" : "POST-TRAIN"}</span></div></article>`,
)
.join("");
datasetMedia = $$("#dataset-grid video").map((video) =>
registerMedia({ element: video, videos: [video], cost: 1 }),
);
}
$("#copy-citation").addEventListener("click", async () => {
const citation = $("#citation").textContent;
try {
if (navigator.clipboard && window.isSecureContext)
await navigator.clipboard.writeText(citation);
else {
const textarea = document.createElement("textarea");
textarea.value = citation;
textarea.style.cssText = "position:fixed;left:-9999px";
document.body.append(textarea);
textarea.select();
const copied = document.execCommand("copy");
textarea.remove();
if (!copied) throw new Error("Copy unavailable");
}
$("#citation-status").textContent = "BibTeX copied.";
} catch {
$("#citation-status").textContent = "Select the citation text to copy it.";
}
});
async function init() {
try {
const content = await Promise.all(
["datasets", "demos", "paper"].map(async (name) => {
const revision = name === "paper" ? "paper-tables12-v1-20261029"
: name === "demos" ? "texture-master-20261030-v6-inline1" : "dataset-timing-v2-20261029";
const response = await fetch(`content/${name}.json?v=${revision}`);
if (!response.ok) throw new Error(`Could not load ${name}`);
return response.json();
}),
);
const [datasetContent, demos, paper] = content;
datasets = datasetContent;
initResearch(paper);
initMotionGallery(demos);
await initNavigation(paper);
$("#citation").textContent = paper.citation.bibtex;
renderDatasets();
} catch (error) {
const message = "Interactive content could not load. Serve this folder with a local HTTP server and reload.";
$("#page-status").textContent = message;
console.error(error);
}
}
init();
initCinematic();
initPlayground();