codebook / assets /js /category.js
vidhimudaliar's picture
Update assets/js/category.js
9525cad verified
// assets/js/category.js
const CSV_PATH = "cleaned_data.csv";
/* >>> DATASET VIDEO BASE <<< */
const VIDEO_DATASET_BASE =
"https://huggingface.co/datasets/therarelab/codebook-videos/resolve/main/videos/";
const params = new URLSearchParams(window.location.search);
const cat = (params.get("cat") || "").trim();
const titleEl = document.getElementById("catTitle");
const defEl = document.getElementById("catDef");
const repMetaEl = document.getElementById("repMeta");
const repGrid = document.getElementById("repGrid");
const repEmpty = document.getElementById("repEmpty");
const instCountEl = document.getElementById("instCount");
const instVideoCountEl = document.getElementById("instVideoCount");
const tbody = document.querySelector("#catTable tbody");
function parseCSV(text) {
const lines = text.trim().split("\n");
const header = lines[0].split(",").map(s => s.trim());
const rows = [];
for (let i = 1; i < lines.length; i++) {
const cols = lines[i].split(",");
const obj = {};
for (let j = 0; j < header.length; j++) {
obj[header[j]] = (cols[j] ?? "").trim();
}
rows.push(obj);
}
return rows;
}
function setHeader(failureInfo) {
if (!cat) {
titleEl.textContent = "No category specified";
defEl.textContent = "Return to Home and select a category.";
return;
}
titleEl.textContent = failureInfo?.name || cat;
defEl.textContent = failureInfo?.definition || "";
document.title = `${cat} — Failure Category`;
}
const failureInfo =
window.FAILURE_MAP?.[cat] ||
window.FAILURES?.find(f => f.name === cat);
setHeader(failureInfo);
/* ---------------- Representative Video ---------------- */
function renderRep(instance) {
repGrid.innerHTML = "";
if (!instance) {
repEmpty.hidden = false;
repMetaEl.textContent = "";
return;
}
repEmpty.hidden = true;
const filename = instance.filename;
const label = instance.label;
const start = instance.start;
const end = instance.end;
const video_url =
VIDEO_DATASET_BASE + encodeURIComponent(filename);
repMetaEl.textContent =
`Example: ${filename} (frames ${start}-${end})`;
const wrap = document.createElement("div");
wrap.className = "video-item";
wrap.innerHTML = `
<video preload="metadata" controls>
<source src="${video_url}" type="video/mp4">
</video>
<div class="video-label">${label}</div>
`;
const videoEl = wrap.querySelector("video");
attachLabeledLoop(videoEl, {
label,
startFrame: start,
endFrame: end,
fps: DEFAULT_FPS
});
repGrid.appendChild(wrap);
}
/* ---------------- Table ---------------- */
function renderTable(instances) {
tbody.innerHTML = "";
const uniqueVideos = new Set();
for (const r of instances) {
uniqueVideos.add(r.filename);
const video_url =
VIDEO_DATASET_BASE + encodeURIComponent(r.filename);
const tr = document.createElement("tr");
tr.innerHTML = `
<td>${r.filename}</td>
<td>${r.start}-${r.end}</td>
<td class="video-cell">
<video preload="metadata" controls>
<source src="${video_url}" type="video/mp4">
</video>
</td>
`;
const videoEl = tr.querySelector("video");
attachLabeledLoop(videoEl, {
label: r.label,
startFrame: r.start,
endFrame: r.end,
fps: DEFAULT_FPS
});
tbody.appendChild(tr);
}
instCountEl.textContent = `${instances.length} segments`;
instVideoCountEl.textContent = `${uniqueVideos.size} videos`;
}
/* ---------------- Load CSV ---------------- */
fetch(CSV_PATH)
.then(r => r.text())
.then(text => {
const rows = parseCSV(text);
const instances = rows
.filter(r => String(r.label || "").trim() === cat)
.filter(r => r.filename && r.start !== "" && r.end !== "");
instances.sort((a, b) => {
if (a.filename !== b.filename)
return a.filename.localeCompare(b.filename);
return Number(a.start) - Number(b.start);
});
renderRep(instances[0]);
renderTable(instances);
})
.catch(err => {
console.error(err);
repEmpty.hidden = false;
repEmpty.textContent = "Could not load cleaned_data.csv.";
tbody.innerHTML =
`<tr><td colspan="3">Could not load cleaned_data.csv</td></tr>`;
});