BibTest.js: Difference between revisions
From Illustrations in German Translations of Mark Twain's Works
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
/* ========================= | |||
STATE | |||
========================= */ | |||
const activeTags = new Set(); | const activeTags = new Set(); | ||
/* TAG | /* ========================= | ||
TAG FILTERING (GLOBAL) | |||
========================= */ | |||
document.querySelectorAll(".tag").forEach(tag => { | document.querySelectorAll(".tag").forEach(tag => { | ||
| Line 22: | Line 29: | ||
}); | }); | ||
function filterEntries() { | function filterEntries() { | ||
| Line 41: | Line 48: | ||
} | } | ||
/* ========================= | |||
VIEW SWITCH (LIST / NETWORK) | |||
========================= */ | |||
document.querySelectorAll(".view-btn").forEach(btn => { | document.querySelectorAll(".view-btn").forEach(btn => { | ||
btn.addEventListener("click", () => { | btn.addEventListener("click", () => { | ||
| Line 51: | Line 65: | ||
const view = btn.dataset.view; | const view = btn.dataset.view; | ||
document.getElementById("listView") | const listView = document.getElementById("listView"); | ||
const networkView = document.getElementById("networkView"); | |||
listView.style.display = (view === "list") ? "block" : "none"; | |||
networkView.classList.toggle("hidden", view !== "network"); | |||
if (view === "network") { | |||
buildNetwork(); | |||
} | |||
}); | }); | ||
}); | }); | ||
// | |||
/* ========================= | |||
EXPAND ABSTRACTS | |||
========================= */ | |||
document.querySelectorAll(".expand-btn").forEach(btn => { | |||
btn.addEventListener("click", () => { | |||
const abstract = btn.nextElementSibling; | |||
abstract.classList.toggle("hidden"); | |||
btn.textContent = | |||
abstract.classList.contains("hidden") | |||
? "Show Abstract" | |||
: "Hide Abstract"; | |||
}); | |||
}); | |||
/* ========================= | |||
NETWORK VIEW | |||
========================= */ | |||
function buildNetwork() { | function buildNetwork() { | ||
| Line 74: | Line 116: | ||
const entryNodes = []; | const entryNodes = []; | ||
const centerX = container.clientWidth / 2; | |||
const centerY = container.clientHeight / 2; | |||
/* ------------------------- | |||
ENTRY NODES | |||
------------------------- */ | |||
entries.forEach((entry, i) => { | entries.forEach((entry, i) => { | ||
| Line 84: | Line 129: | ||
node.innerText = entry.querySelector("h3").innerText; | node.innerText = entry.querySelector("h3").innerText; | ||
const angle = (i / entries.length) * Math.PI * 2; | |||
const x = centerX + Math.cos(angle) * 250; | |||
const y = centerY + Math.sin(angle) * 250; | |||
node.style.left = x + "px"; | node.style.left = x + "px"; | ||
| Line 94: | Line 141: | ||
entryNodes.push({ node, entry, x, y }); | entryNodes.push({ node, entry, x, y }); | ||
node.addEventListener("click", () => { | node.addEventListener("click", () => { | ||
document.querySelectorAll(".node").forEach(n => | document.querySelectorAll(".node") | ||
.forEach(n => n.classList.remove("highlight")); | |||
node.classList.add("highlight"); | node.classList.add("highlight"); | ||
| Line 105: | Line 150: | ||
}); | }); | ||
// | /* ------------------------- | ||
TAG NODES | |||
------------------------- */ | |||
const tags = entry.dataset.tags.split(" "); | const tags = entry.dataset.tags.split(" "); | ||
| Line 116: | Line 164: | ||
tnode.innerText = tag; | tnode.innerText = tag; | ||
const tx = Math.random() * (container.clientWidth - 100) + 50; | |||
const ty = Math.random() * (container.clientHeight - 100) + 50; | |||
tnode.style.left = tx + "px"; | tnode.style.left = tx + "px"; | ||
| Line 132: | Line 180: | ||
}); | }); | ||
// | /* ------------------------- | ||
EDGES | |||
------------------------- */ | |||
entryNodes.forEach(e => { | entryNodes.forEach(e => { | ||
| Line 140: | Line 191: | ||
const t = tagNodes.get(tag); | const t = tagNodes.get(tag); | ||
if (!t) return; | |||
const line = document.createElement("div"); | const line = document.createElement("div"); | ||
| Line 147: | Line 199: | ||
const dy = t.y - e.y; | const dy = t.y - e.y; | ||
const length = Math.sqrt(dx*dx + dy*dy); | const length = Math.sqrt(dx * dx + dy * dy); | ||
line.style.width = length + "px"; | line.style.width = length + "px"; | ||
| Line 161: | Line 213: | ||
} | } | ||
Revision as of 22:03, 11 May 2026
/* =========================
STATE
========================= */
const activeTags = new Set();
/* =========================
TAG FILTERING (GLOBAL)
========================= */
document.querySelectorAll(".tag").forEach(tag => {
tag.addEventListener("click", () => {
const value = tag.dataset.tag;
if (activeTags.has(value)) {
activeTags.delete(value);
tag.classList.remove("active");
} else {
activeTags.add(value);
tag.classList.add("active");
}
filterEntries();
});
});
function filterEntries() {
document.querySelectorAll(".bib-entry").forEach(entry => {
const entryTags = entry.dataset.tags.split(" ");
const matches =
[...activeTags].every(t => entryTags.includes(t));
if (activeTags.size === 0 || matches) {
entry.style.display = "block";
} else {
entry.style.display = "none";
}
});
}
/* =========================
VIEW SWITCH (LIST / NETWORK)
========================= */
document.querySelectorAll(".view-btn").forEach(btn => {
btn.addEventListener("click", () => {
document.querySelectorAll(".view-btn")
.forEach(b => b.classList.remove("active"));
btn.classList.add("active");
const view = btn.dataset.view;
const listView = document.getElementById("listView");
const networkView = document.getElementById("networkView");
listView.style.display = (view === "list") ? "block" : "none";
networkView.classList.toggle("hidden", view !== "network");
if (view === "network") {
buildNetwork();
}
});
});
/* =========================
EXPAND ABSTRACTS
========================= */
document.querySelectorAll(".expand-btn").forEach(btn => {
btn.addEventListener("click", () => {
const abstract = btn.nextElementSibling;
abstract.classList.toggle("hidden");
btn.textContent =
abstract.classList.contains("hidden")
? "Show Abstract"
: "Hide Abstract";
});
});
/* =========================
NETWORK VIEW
========================= */
function buildNetwork() {
const container = document.getElementById("networkView");
container.innerHTML = "";
const entries = document.querySelectorAll(".bib-entry");
const tagNodes = new Map();
const entryNodes = [];
const centerX = container.clientWidth / 2;
const centerY = container.clientHeight / 2;
/* -------------------------
ENTRY NODES
------------------------- */
entries.forEach((entry, i) => {
const node = document.createElement("div");
node.className = "node entry";
node.innerText = entry.querySelector("h3").innerText;
const angle = (i / entries.length) * Math.PI * 2;
const x = centerX + Math.cos(angle) * 250;
const y = centerY + Math.sin(angle) * 250;
node.style.left = x + "px";
node.style.top = y + "px";
container.appendChild(node);
entryNodes.push({ node, entry, x, y });
node.addEventListener("click", () => {
document.querySelectorAll(".node")
.forEach(n => n.classList.remove("highlight"));
node.classList.add("highlight");
});
/* -------------------------
TAG NODES
------------------------- */
const tags = entry.dataset.tags.split(" ");
tags.forEach(tag => {
if (!tagNodes.has(tag)) {
const tnode = document.createElement("div");
tnode.className = "node tag";
tnode.innerText = tag;
const tx = Math.random() * (container.clientWidth - 100) + 50;
const ty = Math.random() * (container.clientHeight - 100) + 50;
tnode.style.left = tx + "px";
tnode.style.top = ty + "px";
container.appendChild(tnode);
tagNodes.set(tag, { node: tnode, x: tx, y: ty });
}
});
});
/* -------------------------
EDGES
------------------------- */
entryNodes.forEach(e => {
const tags = e.entry.dataset.tags.split(" ");
tags.forEach(tag => {
const t = tagNodes.get(tag);
if (!t) return;
const line = document.createElement("div");
line.className = "edge";
const dx = t.x - e.x;
const dy = t.y - e.y;
const length = Math.sqrt(dx * dx + dy * dy);
line.style.width = length + "px";
line.style.left = e.x + "px";
line.style.top = e.y + "px";
line.style.transform = `rotate(${Math.atan2(dy, dx)}rad)`;
container.appendChild(line);
});
});
}