Files
TaroTime/app/ui-alphabet.js

490 lines
16 KiB
JavaScript
Raw Permalink Normal View History

2026-03-07 01:09:00 -08:00
/* ui-alphabet.js — Multi-alphabet browser (English / Hebrew / Greek / Arabic / Enochian) */
(function () {
"use strict";
2026-03-07 05:17:50 -08:00
const alphabetGematriaUi = window.AlphabetGematriaUi || {};
2026-03-07 14:15:09 -08:00
const alphabetBrowserUi = window.AlphabetBrowserUi || {};
2026-03-07 13:38:13 -08:00
const alphabetKabbalahUi = window.AlphabetKabbalahUi || {};
const alphabetReferenceBuilders = window.AlphabetReferenceBuilders || {};
const alphabetDetailUi = window.AlphabetDetailUi || {};
if (
2026-03-07 14:15:09 -08:00
typeof alphabetBrowserUi.createAlphabetBrowser !== "function"
|| typeof alphabetKabbalahUi.buildCubePlacementButton !== "function"
2026-03-07 13:38:13 -08:00
|| typeof alphabetKabbalahUi.buildFourWorldLayersFromDataset !== "function"
|| typeof alphabetKabbalahUi.createEmptyCubeRefs !== "function"
|| typeof alphabetKabbalahUi.getCubePlacementForHebrewLetter !== "function"
|| typeof alphabetKabbalahUi.getCubePlacementForPlanet !== "function"
|| typeof alphabetKabbalahUi.getCubePlacementForSign !== "function"
|| typeof alphabetKabbalahUi.normalizeId !== "function"
|| typeof alphabetKabbalahUi.normalizeLetterId !== "function"
|| typeof alphabetKabbalahUi.titleCase !== "function"
) {
2026-03-07 14:15:09 -08:00
throw new Error("AlphabetBrowserUi and AlphabetKabbalahUi modules must load before ui-alphabet.js");
2026-03-07 13:38:13 -08:00
}
2026-03-07 05:17:50 -08:00
2026-03-07 01:09:00 -08:00
const state = {
initialized: false,
alphabets: null,
activeAlphabet: "all",
selectedKey: null,
filters: {
query: "",
letterType: ""
},
fourWorldLayers: [],
monthRefsByHebrewId: new Map(),
cubeRefs: {
hebrewPlacementById: new Map(),
signPlacementById: new Map(),
planetPlacementById: new Map(),
pathPlacementByNo: new Map()
2026-03-08 22:24:34 -07:00
},
gematriaDb: null
2026-03-07 01:09:00 -08:00
};
function arabicDisplayName(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.arabicDisplayName(letter);
2026-03-07 01:09:00 -08:00
}
// ── Element cache ────────────────────────────────────────────────────
let listEl, countEl, detailNameEl, detailSubEl, detailBodyEl;
let tabAll, tabHebrew, tabGreek, tabEnglish, tabArabic, tabEnochian;
let searchInputEl, searchClearEl, typeFilterEl;
let gematriaCipherEl, gematriaInputEl, gematriaResultEl, gematriaBreakdownEl;
2026-03-09 14:43:03 -07:00
let gematriaModeEls, gematriaMatchesEl, gematriaInputLabelEl, gematriaCipherLabelEl;
2026-03-07 01:09:00 -08:00
function getElements() {
listEl = document.getElementById("alpha-letter-list");
countEl = document.getElementById("alpha-letter-count");
detailNameEl = document.getElementById("alpha-detail-name");
detailSubEl = document.getElementById("alpha-detail-sub");
detailBodyEl = document.getElementById("alpha-detail-body");
tabAll = document.getElementById("alpha-tab-all");
tabHebrew = document.getElementById("alpha-tab-hebrew");
tabGreek = document.getElementById("alpha-tab-greek");
tabEnglish = document.getElementById("alpha-tab-english");
tabArabic = document.getElementById("alpha-tab-arabic");
tabEnochian = document.getElementById("alpha-tab-enochian");
searchInputEl = document.getElementById("alpha-search-input");
searchClearEl = document.getElementById("alpha-search-clear");
typeFilterEl = document.getElementById("alpha-type-filter");
gematriaCipherEl = document.getElementById("alpha-gematria-cipher");
gematriaInputEl = document.getElementById("alpha-gematria-input");
gematriaResultEl = document.getElementById("alpha-gematria-result");
gematriaBreakdownEl = document.getElementById("alpha-gematria-breakdown");
2026-03-09 14:43:03 -07:00
gematriaModeEls = Array.from(document.querySelectorAll("input[name='alpha-tool-mode']"));
2026-03-09 03:07:02 -07:00
gematriaMatchesEl = document.getElementById("alpha-gematria-matches");
gematriaInputLabelEl = document.getElementById("alpha-gematria-input-label");
gematriaCipherLabelEl = document.getElementById("alpha-gematria-cipher-label");
2026-03-07 01:09:00 -08:00
}
2026-03-07 05:17:50 -08:00
function getGematriaElements() {
getElements();
2026-03-07 01:09:00 -08:00
return {
2026-03-07 05:17:50 -08:00
cipherEl: gematriaCipherEl,
inputEl: gematriaInputEl,
resultEl: gematriaResultEl,
2026-03-09 03:07:02 -07:00
breakdownEl: gematriaBreakdownEl,
2026-03-09 14:43:03 -07:00
modeEls: gematriaModeEls,
2026-03-09 03:07:02 -07:00
matchesEl: gematriaMatchesEl,
inputLabelEl: gematriaInputLabelEl,
cipherLabelEl: gematriaCipherLabelEl
2026-03-07 01:09:00 -08:00
};
}
function ensureGematriaCalculator() {
2026-03-07 05:17:50 -08:00
alphabetGematriaUi.init?.({
getAlphabets: () => state.alphabets,
2026-03-08 22:24:34 -07:00
getGematriaDb: () => state.gematriaDb,
2026-03-07 05:17:50 -08:00
getGematriaElements
2026-03-07 01:09:00 -08:00
});
2026-03-07 05:17:50 -08:00
alphabetGematriaUi.ensureCalculator?.();
2026-03-07 01:09:00 -08:00
}
// ── Data helpers ─────────────────────────────────────────────────────
function getLetters() {
2026-03-07 14:15:09 -08:00
return browserUi.getLetters();
2026-03-07 01:09:00 -08:00
}
function alphabetForLetter(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.alphabetForLetter(letter);
2026-03-07 01:09:00 -08:00
}
function letterKeyByAlphabet(alphabet, letter) {
2026-03-07 14:15:09 -08:00
return browserUi.letterKeyByAlphabet(alphabet, letter);
2026-03-07 01:09:00 -08:00
}
function letterKey(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.letterKey(letter);
2026-03-07 01:09:00 -08:00
}
function displayGlyph(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.displayGlyph(letter);
2026-03-07 01:09:00 -08:00
}
function displayLabel(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.displayLabel(letter);
2026-03-07 01:09:00 -08:00
}
function displaySub(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.displaySub(letter);
2026-03-07 01:09:00 -08:00
}
function normalizeLetterType(value) {
2026-03-07 14:15:09 -08:00
return browserUi.normalizeLetterType(value);
2026-03-07 01:09:00 -08:00
}
function getHebrewLetterTypeMap() {
2026-03-07 14:15:09 -08:00
return browserUi.getHebrewLetterTypeMap();
2026-03-07 01:09:00 -08:00
}
function resolveLetterType(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.resolveLetterType(letter);
2026-03-07 01:09:00 -08:00
}
function buildLetterSearchText(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.buildLetterSearchText(letter);
2026-03-07 01:09:00 -08:00
}
function getFilteredLetters() {
2026-03-07 14:15:09 -08:00
return browserUi.getFilteredLetters();
2026-03-07 01:09:00 -08:00
}
function syncFilterControls() {
2026-03-07 14:15:09 -08:00
browserUi.syncFilterControls();
2026-03-07 01:09:00 -08:00
}
function applyFiltersAndRender() {
2026-03-07 14:15:09 -08:00
browserUi.applyFiltersAndRender();
2026-03-07 01:09:00 -08:00
}
function bindFilterControls() {
2026-03-07 14:15:09 -08:00
browserUi.bindFilterControls();
2026-03-07 01:09:00 -08:00
}
function enochianGlyphKey(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.enochianGlyphKey(letter);
2026-03-07 01:09:00 -08:00
}
function enochianGlyphCode(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.enochianGlyphCode(letter);
2026-03-07 01:09:00 -08:00
}
function enochianGlyphUrl(letter) {
2026-03-07 14:15:09 -08:00
return browserUi.enochianGlyphUrl(letter);
2026-03-07 01:09:00 -08:00
}
function enochianGlyphImageHtml(letter, className) {
2026-03-07 14:15:09 -08:00
return browserUi.enochianGlyphImageHtml(letter, className);
2026-03-07 01:09:00 -08:00
}
// ── List rendering ────────────────────────────────────────────────────
function renderList() {
2026-03-07 14:15:09 -08:00
browserUi.renderList();
2026-03-07 01:09:00 -08:00
}
// ── Detail rendering ──────────────────────────────────────────────────
function renderDetail(letter) {
if (!detailNameEl) return;
const alphabet = alphabetForLetter(letter);
detailNameEl.replaceChildren();
if (alphabet === "enochian") {
const image = document.createElement("img");
image.className = "alpha-enochian-glyph-img alpha-enochian-glyph-img--detail";
image.src = enochianGlyphUrl(letter);
image.alt = `Enochian ${enochianGlyphKey(letter) || "?"}`;
image.loading = "lazy";
image.decoding = "async";
image.addEventListener("error", () => {
detailNameEl.textContent = enochianGlyphKey(letter) || "?";
});
detailNameEl.appendChild(image);
} else {
detailNameEl.textContent = displayGlyph(letter);
}
detailNameEl.classList.add("alpha-detail-glyph");
detailNameEl.classList.toggle("alpha-detail-glyph--arabic", alphabet === "arabic");
detailNameEl.classList.toggle("alpha-detail-glyph--enochian", alphabet === "enochian");
2026-03-07 05:17:50 -08:00
if (typeof alphabetDetailUi.renderDetail === "function") {
alphabetDetailUi.renderDetail(getDetailRenderContext(letter, alphabet));
}
2026-03-07 01:09:00 -08:00
}
function card(title, bodyHTML) {
return `<div class="planet-meta-card"><strong>${title}</strong><div class="planet-text">${bodyHTML}</div></div>`;
}
const PLANET_SYMBOLS = {
mercury: "☿︎", luna: "☾︎", venus: "♀︎", sol: "☉︎",
jupiter: "♃︎", mars: "♂︎", saturn: "♄︎"
};
const ZODIAC_SYMBOLS = {
aries: "♈︎", taurus: "♉︎", gemini: "♊︎", cancer: "♋︎",
leo: "♌︎", virgo: "♍︎", libra: "♎︎", scorpio: "♏︎",
sagittarius: "♐︎", capricorn: "♑︎", aquarius: "♒︎", pisces: "♓︎"
};
const HEBREW_DOUBLE_DUALITY = {
bet: { left: "Life", right: "Death" },
gimel: { left: "Peace", right: "War" },
dalet: { left: "Wisdom", right: "Folly" },
kaf: { left: "Wealth", right: "Poverty" },
pe: { left: "Beauty", right: "Ugliness" },
resh: { left: "Fruitfulness", right: "Sterility" },
tav: { left: "Dominion", right: "Slavery" }
};
function normalizeId(value) {
2026-03-07 13:38:13 -08:00
return alphabetKabbalahUi.normalizeId(value);
2026-03-07 01:09:00 -08:00
}
2026-03-07 13:38:13 -08:00
function normalizeLetterId(value) {
return alphabetKabbalahUi.normalizeLetterId(value);
2026-03-07 01:09:00 -08:00
}
2026-03-07 13:38:13 -08:00
function titleCase(value) {
return alphabetKabbalahUi.titleCase(value);
}
2026-03-07 01:09:00 -08:00
2026-03-07 13:38:13 -08:00
function buildFourWorldLayersFromDataset(magickDataset) {
return alphabetKabbalahUi.buildFourWorldLayersFromDataset(magickDataset);
2026-03-07 01:09:00 -08:00
}
function buildMonthReferencesByHebrew(referenceData, alphabets) {
2026-03-07 05:17:50 -08:00
if (typeof alphabetReferenceBuilders.buildMonthReferencesByHebrew !== "function") {
return new Map();
2026-03-07 01:09:00 -08:00
}
2026-03-07 05:17:50 -08:00
return alphabetReferenceBuilders.buildMonthReferencesByHebrew(referenceData, alphabets);
2026-03-07 01:09:00 -08:00
}
function createEmptyCubeRefs() {
2026-03-07 13:38:13 -08:00
return alphabetKabbalahUi.createEmptyCubeRefs();
2026-03-07 01:09:00 -08:00
}
function buildCubeReferences(magickDataset) {
2026-03-07 05:17:50 -08:00
if (typeof alphabetReferenceBuilders.buildCubeReferences !== "function") {
return createEmptyCubeRefs();
}
2026-03-07 01:09:00 -08:00
2026-03-07 05:17:50 -08:00
return alphabetReferenceBuilders.buildCubeReferences(magickDataset);
2026-03-07 01:09:00 -08:00
}
function getCubePlacementForHebrewLetter(hebrewLetterId, pathNo = null) {
2026-03-07 13:38:13 -08:00
return alphabetKabbalahUi.getCubePlacementForHebrewLetter(state.cubeRefs, hebrewLetterId, pathNo);
2026-03-07 01:09:00 -08:00
}
function getCubePlacementForPlanet(planetId) {
2026-03-07 13:38:13 -08:00
return alphabetKabbalahUi.getCubePlacementForPlanet(state.cubeRefs, planetId);
2026-03-07 01:09:00 -08:00
}
function getCubePlacementForSign(signId) {
2026-03-07 13:38:13 -08:00
return alphabetKabbalahUi.getCubePlacementForSign(state.cubeRefs, signId);
2026-03-07 01:09:00 -08:00
}
function cubePlacementBtn(placement, fallbackDetail = null) {
2026-03-07 13:38:13 -08:00
return alphabetKabbalahUi.buildCubePlacementButton(placement, navBtn, fallbackDetail);
2026-03-07 01:09:00 -08:00
}
function cap(s) { return s ? s.charAt(0).toUpperCase() + s.slice(1) : ""; }
function navBtn(label, event, detail) {
const attrs = Object.entries(detail).map(([k, v]) => `data-${k}="${v}"`).join(" ");
return `<button class="alpha-nav-btn" data-event="${event}" ${attrs}>${label} ↗</button>`;
}
2026-03-07 05:17:50 -08:00
function getDetailRenderContext(letter, alphabet) {
return {
letter,
alphabet,
detailSubEl,
detailBodyEl,
alphabets: state.alphabets,
fourWorldLayers: state.fourWorldLayers,
monthRefsByHebrewId: state.monthRefsByHebrewId,
PLANET_SYMBOLS,
ZODIAC_SYMBOLS,
HEBREW_DOUBLE_DUALITY,
card,
navBtn,
cap,
normalizeId,
normalizeLetterId,
getCubePlacementForPlanet,
getCubePlacementForSign,
getCubePlacementForHebrewLetter,
cubePlacementBtn,
arabicDisplayName,
enochianGlyphImageHtml,
attachDetailListeners
};
2026-03-07 01:09:00 -08:00
}
2026-03-07 14:15:09 -08:00
const browserUi = alphabetBrowserUi.createAlphabetBrowser({
state,
normalizeId,
getDomRefs: () => ({
listEl,
countEl,
detailNameEl,
detailSubEl,
detailBodyEl,
tabAll,
tabHebrew,
tabGreek,
tabEnglish,
tabArabic,
tabEnochian,
searchInputEl,
searchClearEl,
typeFilterEl
}),
renderDetail
});
2026-03-07 01:09:00 -08:00
// ── Event delegation on detail body ──────────────────────────────────
function attachDetailListeners() {
if (!detailBodyEl) return;
// Nav buttons — generic: forward all data-* (except data-event) as the event detail
detailBodyEl.querySelectorAll(".alpha-nav-btn[data-event]").forEach((btn) => {
btn.addEventListener("click", () => {
const evtName = btn.dataset.event;
const detail = {};
Object.entries(btn.dataset).forEach(([key, val]) => {
if (key === "event") return;
// Convert kebab data keys to camelCase (e.g. planet-id → planetId)
const camel = key.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
detail[camel] = isNaN(Number(val)) || val === "" ? val : Number(val);
});
document.dispatchEvent(new CustomEvent(evtName, { detail }));
});
});
// Sister letter cross-navigation within this section
detailBodyEl.querySelectorAll(".alpha-sister-btn[data-alpha]").forEach((btn) => {
btn.addEventListener("click", () => {
const alpha = btn.dataset.alpha;
const key = btn.dataset.key;
switchAlphabet(alpha, key);
});
});
}
// ── Selection ─────────────────────────────────────────────────────────
function selectLetter(key) {
2026-03-07 14:15:09 -08:00
browserUi.selectLetter(key);
2026-03-07 01:09:00 -08:00
}
// ── Alphabet switching ────────────────────────────────────────────────
function switchAlphabet(alpha, selectKey) {
2026-03-07 14:15:09 -08:00
browserUi.switchAlphabet(alpha, selectKey);
2026-03-07 01:09:00 -08:00
}
function updateTabs() {
2026-03-07 14:15:09 -08:00
browserUi.updateTabs();
2026-03-07 01:09:00 -08:00
}
function resetDetail() {
2026-03-07 14:15:09 -08:00
browserUi.resetDetail();
2026-03-07 01:09:00 -08:00
}
// ── Public init ───────────────────────────────────────────────────────
function ensureAlphabetSection(magickDataset, referenceData = null) {
const grouped = magickDataset?.grouped || {};
const alphabetData = (grouped["alphabets"] && grouped["alphabets"]["hebrew"])
? grouped["alphabets"]
: null;
if (alphabetData) {
state.alphabets = alphabetData;
2026-03-07 05:17:50 -08:00
alphabetGematriaUi.refreshScriptMap?.();
2026-03-07 01:09:00 -08:00
}
state.fourWorldLayers = buildFourWorldLayersFromDataset(magickDataset);
state.cubeRefs = buildCubeReferences(magickDataset);
if (referenceData && state.alphabets) {
state.monthRefsByHebrewId = buildMonthReferencesByHebrew(referenceData, state.alphabets);
}
2026-03-08 22:24:34 -07:00
state.gematriaDb = referenceData?.gematriaCiphers || null;
2026-03-07 01:09:00 -08:00
if (state.initialized) {
ensureGematriaCalculator();
syncFilterControls();
renderList();
const letters = getFilteredLetters();
const selected = letters.find((entry) => letterKey(entry) === state.selectedKey) || letters[0];
if (selected) {
renderDetail(selected);
} else {
resetDetail();
if (detailSubEl) {
detailSubEl.textContent = "No letters match the current filter.";
}
}
return;
}
state.initialized = true;
// alphabets.json is a top-level file → grouped["alphabets"] = the data object
getElements();
ensureGematriaCalculator();
bindFilterControls();
syncFilterControls();
if (!state.alphabets) {
if (detailSubEl) detailSubEl.textContent = "Alphabet data not loaded.";
return;
}
// Attach tab listeners
[tabAll, tabHebrew, tabGreek, tabEnglish, tabArabic, tabEnochian].forEach((btn) => {
if (!btn) return;
btn.addEventListener("click", () => {
switchAlphabet(btn.dataset.alpha, null);
});
});
switchAlphabet("all", null);
}
// ── Incoming navigation ───────────────────────────────────────────────
function selectLetterByHebrewId(hebrewLetterId) {
switchAlphabet("hebrew", hebrewLetterId);
}
function selectGreekLetterByName(name) {
switchAlphabet("greek", name);
}
function selectEnglishLetter(letter) {
switchAlphabet("english", letter);
}
function selectArabicLetter(name) {
switchAlphabet("arabic", name);
}
function selectEnochianLetter(id) {
switchAlphabet("enochian", id);
}
window.AlphabetSectionUi = {
ensureAlphabetSection,
selectLetterByHebrewId,
selectGreekLetterByName,
selectEnglishLetter,
selectArabicLetter,
selectEnochianLetter
};
})();