MediaWiki

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:
let BIB_DATA = [];
(async function () {
let ACTIVE_TAGS = new Set();


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


document.addEventListener("DOMContentLoaded", async () => {
let DATA = [];
    await loadData();
let ACTIVE_TAGS = new Set();
    render();
});


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


/* =========================
document.addEventListener("DOMContentLoaded", init);
  LOAD DATA FROM WIKI
========================= */


async function loadData() {
async function init() {
     const url = "/index.php?title=BibliographyData&action=raw";
     await loadData();
 
     renderTags();
    const res = await fetch(url);
     renderList();
    const text = await res.text();
 
     BIB_DATA = JSON.parse(text);
 
     console.log("📚 Loaded entries:", BIB_DATA.length);
}
}


/* =========================
// -------------------- LOAD DATA --------------------
  TAG EXTRACTION
========================= */


function getAllTags(data) {
async function loadData() {
     const tagSet = new Set();
     const res = await fetch(DATA_URL);
    DATA = await res.json();


     data.forEach(item => {
     // Alphabetisch nach Titel
        (item.tags || []).forEach(t => tagSet.add(t));
     DATA.sort((a, b) =>
     });
        (a.title || "").localeCompare(b.title || "")
 
    );
    return [...tagSet].sort((a, b) => a.localeCompare(b));
}
}


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


/* =========================
function renderTags() {
  RENDER TAG BAR
    const tagBar = document.getElementById("tagBar");
========================= */
    tagBar.innerHTML = "";


function renderTags() {
     const allTags = new Set();
     const container = document.getElementById("tagBar");
    container.innerHTML = "";


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


     tags.forEach(tag => {
     [...allTags].sort().forEach(tag => {
         const el = document.createElement("span");
         const el = document.createElement("span");
         el.className = "tag" + (ACTIVE_TAGS.has(tag) ? " active" : "");
         el.className = "tag inactive";
         el.textContent = tag;
         el.textContent = tag;
        el.dataset.tag = tag;


         el.onclick = () => {
         el.onclick = () => toggleTag(tag, el);
            if (ACTIVE_TAGS.has(tag)) {
                ACTIVE_TAGS.delete(tag);
            } else {
                ACTIVE_TAGS.add(tag);
            }
            render();
        };


         container.appendChild(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();
  FILTER LOGIC
========================= */
 
function filterData(data) {
    if (ACTIVE_TAGS.size === 0) return data;
 
     return data.filter(item =>
        (item.tags || []).some(t => ACTIVE_TAGS.has(t))
    );
}
}


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


/* =========================
function renderList() {
  SORT (ALPHABETICAL)
========================= */
 
function sortData(data) {
    return [...data].sort((a, b) =>
        (a.authors?.[0]?.family || "Unknown")
            .localeCompare(b.authors?.[0]?.family || "Unknown")
    );
}
 
 
/* =========================
  RENDER LIST VIEW
========================= */
 
function renderList(data) {
     const container = document.getElementById("listView");
     const container = document.getElementById("listView");
     container.innerHTML = "";
     container.innerHTML = "";


     data.forEach(item => {
     let filtered = DATA;


         const author = item.authors?.[0]
    if (ACTIVE_TAGS.size > 0) {
             ? `${item.authors[0].family}, ${item.authors[0].given || ""}`
         filtered = DATA.filter(item =>
            : "Unknown Author";
             item.tags && item.tags.some(t => ACTIVE_TAGS.has(t))
 
         );
        const tagsHTML = (item.tags || []).map(tag =>
    }
            `<span class="tag small ${ACTIVE_TAGS.has(tag) ? "active" : ""}"
                  onclick="toggleTag('${tag}')">${tag}</span>`
         ).join(" ");


    filtered.forEach(item => {
         const div = document.createElement("div");
         const div = document.createElement("div");
         div.className = "bib-entry";
         div.className = "bib-entry";
        div.innerHTML = `
            <h3>${author}. <i>${item.title}</i>. ${item.year || ""}</h3>
            <div class="bib-tags">${tagsHTML}</div>
            <p class="short-abstract">${item.abstract || ""}</p>


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


         container.appendChild(div);
         container.appendChild(div);
Line 131: Line 90:
}
}


// -------------------- 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>
  TAG TOGGLE FROM LIST
========================= */


function toggleTag(tag) {
        ${item.url ? `<a href="${item.url}" target="_blank">Source</a>` : ""}
    if (ACTIVE_TAGS.has(tag)) {
     `;
        ACTIVE_TAGS.delete(tag);
    } else {
        ACTIVE_TAGS.add(tag);
    }
     render();
}
}


// -------------------- GLOBAL TAG CLICK (from entries) --------------------
window.__toggleTagFromEntry = function(tag) {
    const tagBarTags = document.querySelectorAll("#tagBar .tag");


/* =========================
    ACTIVE_TAGS.has(tag)
  MAIN RENDER PIPELINE
        ? ACTIVE_TAGS.delete(tag)
========================= */
        : ACTIVE_TAGS.add(tag);


function render() {
    tagBarTags.forEach(t => {
    const filtered = filterData(BIB_DATA);
        if (t.dataset.tag === tag) {
     const sorted = sortData(filtered);
            t.classList.toggle("active", ACTIVE_TAGS.has(tag));
            t.classList.toggle("inactive", !ACTIVE_TAGS.has(tag));
        }
     });


    renderTags();
     renderList();
     renderList(sorted);
};
}
console.log("📚 Bibliography system loading...");


// alles deine Logik hier
})();

Revision as of 23:43, 11 May 2026

(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();
};

})();