MediaWiki

MediaWiki:BibTest.js

From Illustrations in German Translations of Mark Twain's Works

Revision as of 23:43, 11 May 2026 by HMHTEST (talk | contribs)

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.
(async function () {

const DATA_URL = "https://illus.twainframe.org/index.php?title=BibliographyData&action=raw&ctype=application/json";

let DATA = [];
let ACTIVE_TAGS = new Set();

// -------------------- INIT --------------------

document.addEventListener("DOMContentLoaded", init);

async function init() {
    await loadData();
    renderTags();
    renderList();
}

// -------------------- LOAD DATA --------------------

async function loadData() {
    const res = await fetch(DATA_URL);
    DATA = await res.json();

    // Alphabetisch nach Titel
    DATA.sort((a, b) =>
        (a.title || "").localeCompare(b.title || "")
    );
}

// -------------------- TAG BAR --------------------

function renderTags() {
    const tagBar = document.getElementById("tagBar");
    tagBar.innerHTML = "";

    const allTags = new Set();

    DATA.forEach(item => {
        (item.tags || []).forEach(t => allTags.add(t));
    });

    [...allTags].sort().forEach(tag => {
        const el = document.createElement("span");
        el.className = "tag inactive";
        el.textContent = tag;
        el.dataset.tag = tag;

        el.onclick = () => toggleTag(tag, el);

        tagBar.appendChild(el);
    });
}

function toggleTag(tag, el) {
    if (ACTIVE_TAGS.has(tag)) {
        ACTIVE_TAGS.delete(tag);
        el.classList.remove("active");
        el.classList.add("inactive");
    } else {
        ACTIVE_TAGS.add(tag);
        el.classList.add("active");
        el.classList.remove("inactive");
    }

    renderList();
}

// -------------------- LIST VIEW --------------------

function renderList() {
    const container = document.getElementById("listView");
    container.innerHTML = "";

    let filtered = DATA;

    if (ACTIVE_TAGS.size > 0) {
        filtered = DATA.filter(item =>
            item.tags && item.tags.some(t => ACTIVE_TAGS.has(t))
        );
    }

    filtered.forEach(item => {
        const div = document.createElement("div");
        div.className = "bib-entry";

        div.innerHTML = buildEntry(item);

        container.appendChild(div);
    });
}

// -------------------- ENTRY TEMPLATE --------------------

function buildEntry(item) {

    const authors = (item.authors || [])
        .map(a => {
            if (typeof a === "string") return a;
            return (a.family || "") + (a.given ? ", " + a.given : "");
        })
        .join(", ");

    const tags = (item.tags || []).map(t =>
        `<span class="tag ${ACTIVE_TAGS.has(t) ? 'active' : 'inactive'}"
               data-tag="${t}"
               onclick="window.__toggleTagFromEntry('${t}')">
            ${t}
        </span>`
    ).join(" ");

    return `
        <h3>${authors || "Unknown"}. <i>${item.title || "Untitled"}</i>. ${item.year || ""}</h3>

        <div class="bib-tags">${tags}</div>

        <p class="short-abstract">${item.abstract || ""}</p>

        ${item.url ? `<a href="${item.url}" target="_blank">Source</a>` : ""}
    `;
}

// -------------------- GLOBAL TAG CLICK (from entries) --------------------

window.__toggleTagFromEntry = function(tag) {
    const tagBarTags = document.querySelectorAll("#tagBar .tag");

    ACTIVE_TAGS.has(tag)
        ? ACTIVE_TAGS.delete(tag)
        : ACTIVE_TAGS.add(tag);

    tagBarTags.forEach(t => {
        if (t.dataset.tag === tag) {
            t.classList.toggle("active", ACTIVE_TAGS.has(tag));
            t.classList.toggle("inactive", !ACTIVE_TAGS.has(tag));
        }
    });

    renderList();
};

})();