MediaWiki:BibTest.js
From Illustrations in German Translations of Mark Twain's Works
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
let rawData = [];
let activeTags = new Set();
/* =========================
INIT
========================= */
document.addEventListener("DOMContentLoaded", () => {
if (typeof BibliographyData !== "undefined") {
loadBibliography();
}
document.getElementById("updateBib").addEventListener("click", reloadBibliography);
});
/* =========================
LOAD + RENDER
========================= */
function loadBibliography() {
rawData = normalizeData(BibliographyData);
renderTags(rawData);
renderList(rawData);
}
/* =========================
NORMALIZE ZOTERO DATA
========================= */
function normalizeData(data) {
return data.map(item => ({
title: item.title || "Untitled",
date: item.date || "",
author: item.creators?.[0]?.lastName || "Unknown",
tags: (item.tags || []).map(t => t.tag),
abstractNote: item.abstractNote || ""
}));
}
/* =========================
GLOBAL TAG BAR
========================= */
function renderTags(data) {
const container = document.getElementById("globalTags");
const tagSet = new Set();
data.forEach(item => {
item.tags.forEach(t => tagSet.add(t));
});
container.innerHTML = "";
[...tagSet].sort().forEach(tag => {
const el = document.createElement("span");
el.className = "tag";
el.dataset.tag = tag;
el.innerText = tag;
el.addEventListener("click", () => toggleTag(tag, el));
container.appendChild(el);
});
}
/* =========================
TAG TOGGLE
========================= */
function toggleTag(tag, el) {
if (activeTags.has(tag)) {
activeTags.delete(tag);
el.classList.remove("active");
} else {
activeTags.add(tag);
el.classList.add("active");
}
applyFilter();
syncEntryTags();
}
/* =========================
FILTER ENTRIES
========================= */
function applyFilter() {
document.querySelectorAll(".bib-entry").forEach(entry => {
const tags = (entry.dataset.tags || "").split(" ");
const match =
activeTags.size === 0 ||
[...activeTags].every(t => tags.includes(t));
entry.style.display = match ? "block" : "none";
});
}
/* =========================
SYNC TAG VISUAL STATE
========================= */
function syncEntryTags() {
document.querySelectorAll(".bib-entry .tag").forEach(tag => {
const value = tag.dataset.tag;
if (activeTags.has(value)) {
tag.classList.add("active");
} else {
tag.classList.remove("active");
}
});
}
/* =========================
RENDER LIST
========================= */
function renderList(data) {
const container = document.getElementById("listView");
container.innerHTML = "";
// alphabetisch sortieren
data.sort((a, b) =>
a.author.localeCompare(b.author)
);
data.forEach(item => {
const el = document.createElement("div");
el.className = "bib-entry";
el.dataset.tags = item.tags.join(" ");
el.innerHTML = `
<h3>${item.author}. <i>${item.title}</i>. ${item.date}</h3>
<div class="bib-tags">
${item.tags.map(t =>
`<span class="tag" data-tag="${t}">${t}</span>`
).join(" ")}
</div>
<p class="short-abstract">
${item.abstractNote}
</p>
<button class="expand-btn">Show Abstract</button>
<div class="abstract hidden">
<p>${item.abstractNote}</p>
</div>
`;
container.appendChild(el);
});
rebindUI();
syncEntryTags();
applyFilter();
}
/* =========================
UI REBIND
========================= */
function rebindUI() {
document.querySelectorAll(".expand-btn").forEach(btn => {
btn.onclick = () => {
const abs = btn.nextElementSibling;
abs.classList.toggle("hidden");
btn.textContent =
abs.classList.contains("hidden")
? "Show Abstract"
: "Hide Abstract";
};
});
// entry tags → trigger global filter
document.querySelectorAll(".bib-entry .tag").forEach(tag => {
tag.onclick = () => {
const value = tag.dataset.tag;
const global = document.querySelector(
`.bib-tags#globalTags .tag[data-tag="${value}"]`
);
if (global) global.click();
};
});
}
/* =========================
UPDATE BUTTON
========================= */
function reloadBibliography() {
console.log("🔄 Reloading BibliographyData...");
if (typeof BibliographyData === "undefined") {
console.error("BibliographyData not found");
return;
}
rawData = normalizeData(BibliographyData);
activeTags.clear();
document.getElementById("globalTags").innerHTML = "";
loadBibliography();
console.log("✅ Updated");
}