MediaWiki:Common.js: Difference between revisions
From Encyclopedium Universum
mNo edit summary |
Add Pealim-backed Torah citation popups |
||
| Line 1: | Line 1: | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
(function(){ | (function(){ | ||
// Tanakh verse counts | // Tanakh verse counts | ||
| Line 148: | Line 105: | ||
} | } | ||
})(); | |||
/* UKOY Torah citation popups: inline references backed by Pealim Tanakh.v2++ and KJV++ exports. */ | |||
(function () { | |||
const DATA_URL = "/resources/ukoy/verse-citations.json"; | |||
let citationDataPromise = null; | |||
let modal = null; | |||
function fetchCitationData() { | |||
if (!citationDataPromise) { | |||
citationDataPromise = fetch(DATA_URL, { credentials: "same-origin" }).then(function (response) { | |||
if (!response.ok) throw new Error("Unable to load citation data"); | |||
return response.json(); | |||
}); | |||
} | |||
return citationDataPromise; | |||
} | |||
function ensureModal() { | |||
if (modal) return modal; | |||
modal = document.createElement("div"); | |||
modal.className = "ukoy-verse-modal"; | |||
modal.innerHTML = "<div class='ukoy-verse-modal-card' role='dialog' aria-modal='true' aria-label='Torah citation'><button type='button' class='ukoy-verse-modal-close' aria-label='Close'>×</button><div class='ukoy-verse-modal-body'></div></div>"; | |||
document.body.appendChild(modal); | |||
modal.addEventListener("click", function (event) { | |||
if (event.target === modal || event.target.classList.contains("ukoy-verse-modal-close")) closeModal(); | |||
}); | |||
document.addEventListener("keydown", function (event) { if (event.key === "Escape") closeModal(); }); | |||
return modal; | |||
} | |||
function closeModal() { if (modal) modal.classList.remove("is-open"); } | |||
function escapeHtml(value) { | |||
return String(value || "").replace(/[&<>'"]/g, function (char) { | |||
return { "&": "&", "<": "<", ">": ">", "'": "'", '"': """ }[char]; | |||
}); | |||
} | |||
function renderCitation(entry) { | |||
if (!entry) return "<div class='ukoy-verse-error'>Citation data not found.</div>"; | |||
const verses = entry.verses || []; | |||
return "<div class='ukoy-verse-heading'>" + escapeHtml(entry.label) + "</div>" + | |||
verses.map(function (verse) { | |||
return "<section class='ukoy-verse-entry'>" + | |||
"<div class='ukoy-verse-ref'>" + escapeHtml(verse.reference) + "</div>" + | |||
"<div class='ukoy-verse-label'>Tanakh.v2++ interlinear</div>" + | |||
(verse.tanakhInterlinearHtml || "<div class='ukoy-missing'>Tanakh.v2++ verse not available.</div>") + | |||
"<div class='ukoy-verse-label'>KJV++ plain English rendering</div>" + | |||
"<div class='ukoy-kjv-text'>" + escapeHtml(verse.kjvText || "") + "</div>" + | |||
"</section>"; | |||
}).join(""); | |||
} | |||
function openCitation(ref) { | |||
const m = ensureModal(); | |||
const body = m.querySelector(".ukoy-verse-modal-body"); | |||
body.innerHTML = "<div class='ukoy-loading'>Loading citation…</div>"; | |||
m.classList.add("is-open"); | |||
fetchCitationData() | |||
.then(function (data) { body.innerHTML = renderCitation(data[ref]); }) | |||
.catch(function (error) { body.innerHTML = "<div class='ukoy-verse-error'>" + escapeHtml(error.message) + "</div>"; }); | |||
} | |||
document.addEventListener("click", function (event) { | |||
const link = event.target.closest(".ukoy-cite"); | |||
if (!link) return; | |||
event.preventDefault(); | |||
openCitation(link.getAttribute("data-ref")); | |||
}); | |||
})(); | })(); | ||
Revision as of 06:51, 24 May 2026
/* Any JavaScript here will be loaded for all users on every page load. */
(function(){
// Tanakh verse counts
const verseCounts = {
"Genesis": [31,25,24,26,32,22,24,22,29,32,32,20,18,24,21,16,27,33,38,18,34,24,20,67,34,35,46,22,35,43,55,32,20,31,29,43,36,30,23,23,57,38,34,34,31,22,33,26,22,25],
"Exodus": [22,25,22,31,23,30,25,32,35,29,10,51,22,31,27,36,16,27,25,26,37,30,33,18,40,37,21,43,46,38,18,35,23,35,35,38,29,31,43,38],
"Leviticus": [17,16,17,35,19,30,38,36,24,20,47,8,59,57,33,34,16,30,37,27,24,33,44,23,55,46,34],
"Numbers": [54,34,51,49,31,27,89,26,23,36,35,16,33,45,41,50,13,32,22,29,35,41,30,25,18,65,23,31,40,16,54,42,56,29,34,13],
"Deuteronomy": [46,37,29,49,33,25,26,20,29,22,32,32,18,29,23,22,20,22,21,20,23,30,25,22,19,19,26,68,29,20,30,52,29,12],
// Add rest of Tanakh...
};
const title = mw.config.get('wgTitle'); // current wiki page title
const match = title.match(/^(.*?) \((.*?)\)(?: (\d+))?$/);
if (!match) return; // doesn't match expected format
const translitName = match[1];
const englishName = match[2];
const chapterNum = match[3] ? parseInt(match[3], 10) : null;
if (!verseCounts[englishName]) return; // no data for this book
const container = document.getElementById('tanakh-selector');
if (!container) return;
const chapters = verseCounts[englishName];
// Title
const h2 = document.createElement('h2');
h2.textContent = `${translitName} (${englishName}) — Select Chapter & Verse`;
container.appendChild(h2);
// Chapter buttons grid
const chaptersDiv = document.createElement('div');
chaptersDiv.style.display = 'grid';
chaptersDiv.style.gridTemplateColumns = 'repeat(auto-fit, minmax(72px, 1fr))';
chaptersDiv.style.gap = '8px';
container.appendChild(chaptersDiv);
// Verse panel
const versesPanel = document.createElement('div');
versesPanel.style.display = 'none';
versesPanel.style.marginTop = '12px';
container.appendChild(versesPanel);
const versesHeader = document.createElement('div');
versesHeader.style.display = 'flex';
versesHeader.style.justifyContent = 'space-between';
versesHeader.style.alignItems = 'center';
versesPanel.appendChild(versesHeader);
const currentChLabel = document.createElement('strong');
versesHeader.appendChild(currentChLabel);
const closeBtn = document.createElement('button');
closeBtn.textContent = 'Close';
closeBtn.style.cssText = 'background:#eee;border:1px solid #ccc;padding:4px 8px;border-radius:6px;cursor:pointer;';
versesHeader.appendChild(closeBtn);
const versesDiv = document.createElement('div');
versesDiv.style.display = 'flex';
versesDiv.style.flexWrap = 'wrap';
versesDiv.style.gap = '6px';
versesDiv.style.marginTop = '8px';
versesPanel.appendChild(versesDiv);
// Function to open chapter
function openChapter(chNum) {
const verseCount = chapters[chNum - 1];
currentChLabel.textContent = `Chapter ${chNum} — ${verseCount} verses`;
versesDiv.innerHTML = '';
for (let v = 1; v <= verseCount; v++) {
const a = document.createElement('a');
const pageName = `${translitName} (${englishName}) ${chNum}`.replace(/ /g, '_');
a.href = `/wiki/${pageName}#v${v}`;
a.textContent = v;
a.style.cssText = 'display:inline-flex;align-items:center;justify-content:center;padding:6px 8px;border-radius:6px;border:1px solid #e0e0e0;text-decoration:none;min-width:36px;text-align:center;';
versesDiv.appendChild(a);
}
versesPanel.style.display = 'block';
versesPanel.scrollIntoView({behavior:'smooth', block:'nearest'});
}
// Build chapter buttons
chapters.forEach((verseCount, i) => {
const chNum = i + 1;
const btn = document.createElement('button');
btn.type = 'button';
btn.textContent = chNum;
btn.style.cssText = 'padding:10px 8px;border-radius:8px;border:1px solid #d0d0d0;background:#fff;cursor:pointer;';
btn.addEventListener('click', () => openChapter(chNum));
chaptersDiv.appendChild(btn);
});
closeBtn.addEventListener('click', () => {
versesPanel.style.display = 'none';
});
// Auto-open chapter if we are on a chapter page
if (chapterNum) {
openChapter(chapterNum);
}
})();
/* UKOY Torah citation popups: inline references backed by Pealim Tanakh.v2++ and KJV++ exports. */
(function () {
const DATA_URL = "/resources/ukoy/verse-citations.json";
let citationDataPromise = null;
let modal = null;
function fetchCitationData() {
if (!citationDataPromise) {
citationDataPromise = fetch(DATA_URL, { credentials: "same-origin" }).then(function (response) {
if (!response.ok) throw new Error("Unable to load citation data");
return response.json();
});
}
return citationDataPromise;
}
function ensureModal() {
if (modal) return modal;
modal = document.createElement("div");
modal.className = "ukoy-verse-modal";
modal.innerHTML = "<div class='ukoy-verse-modal-card' role='dialog' aria-modal='true' aria-label='Torah citation'><button type='button' class='ukoy-verse-modal-close' aria-label='Close'>×</button><div class='ukoy-verse-modal-body'></div></div>";
document.body.appendChild(modal);
modal.addEventListener("click", function (event) {
if (event.target === modal || event.target.classList.contains("ukoy-verse-modal-close")) closeModal();
});
document.addEventListener("keydown", function (event) { if (event.key === "Escape") closeModal(); });
return modal;
}
function closeModal() { if (modal) modal.classList.remove("is-open"); }
function escapeHtml(value) {
return String(value || "").replace(/[&<>'"]/g, function (char) {
return { "&": "&", "<": "<", ">": ">", "'": "'", '"': """ }[char];
});
}
function renderCitation(entry) {
if (!entry) return "<div class='ukoy-verse-error'>Citation data not found.</div>";
const verses = entry.verses || [];
return "<div class='ukoy-verse-heading'>" + escapeHtml(entry.label) + "</div>" +
verses.map(function (verse) {
return "<section class='ukoy-verse-entry'>" +
"<div class='ukoy-verse-ref'>" + escapeHtml(verse.reference) + "</div>" +
"<div class='ukoy-verse-label'>Tanakh.v2++ interlinear</div>" +
(verse.tanakhInterlinearHtml || "<div class='ukoy-missing'>Tanakh.v2++ verse not available.</div>") +
"<div class='ukoy-verse-label'>KJV++ plain English rendering</div>" +
"<div class='ukoy-kjv-text'>" + escapeHtml(verse.kjvText || "") + "</div>" +
"</section>";
}).join("");
}
function openCitation(ref) {
const m = ensureModal();
const body = m.querySelector(".ukoy-verse-modal-body");
body.innerHTML = "<div class='ukoy-loading'>Loading citation…</div>";
m.classList.add("is-open");
fetchCitationData()
.then(function (data) { body.innerHTML = renderCitation(data[ref]); })
.catch(function (error) { body.innerHTML = "<div class='ukoy-verse-error'>" + escapeHtml(error.message) + "</div>"; });
}
document.addEventListener("click", function (event) {
const link = event.target.closest(".ukoy-cite");
if (!link) return;
event.preventDefault();
openCitation(link.getAttribute("data-ref"));
});
})();
