refactoring
This commit is contained in:
@@ -61,6 +61,8 @@
|
||||
selectedPathNumber: null
|
||||
};
|
||||
|
||||
const kabbalahDetailUi = window.KabbalahDetailUi || {};
|
||||
|
||||
const PLANET_NAME_TO_ID = {
|
||||
saturn: "saturn",
|
||||
jupiter: "jupiter",
|
||||
@@ -88,31 +90,6 @@
|
||||
pisces: "pisces"
|
||||
};
|
||||
|
||||
const PLANET_ID_TO_LABEL = {
|
||||
saturn: "Saturn",
|
||||
jupiter: "Jupiter",
|
||||
mars: "Mars",
|
||||
sol: "Sol",
|
||||
venus: "Venus",
|
||||
mercury: "Mercury",
|
||||
luna: "Luna"
|
||||
};
|
||||
|
||||
const MINOR_RANK_BY_PLURAL = {
|
||||
aces: "Ace",
|
||||
twos: "Two",
|
||||
threes: "Three",
|
||||
fours: "Four",
|
||||
fives: "Five",
|
||||
sixes: "Six",
|
||||
sevens: "Seven",
|
||||
eights: "Eight",
|
||||
nines: "Nine",
|
||||
tens: "Ten"
|
||||
};
|
||||
|
||||
const MINOR_SUITS = ["Wands", "Cups", "Swords", "Disks"];
|
||||
|
||||
const HEBREW_LETTER_ALIASES = {
|
||||
aleph: "alef",
|
||||
alef: "alef",
|
||||
@@ -274,6 +251,22 @@
|
||||
pathLetterToggleEl: document.getElementById("kab-path-letter-toggle"),
|
||||
pathNumberToggleEl: document.getElementById("kab-path-number-toggle"),
|
||||
pathTarotToggleEl: document.getElementById("kab-path-tarot-toggle"),
|
||||
roseCrossContainerEl: document.getElementById("kab-rose-cross-container"),
|
||||
roseDetailNameEl: document.getElementById("kab-rose-detail-name"),
|
||||
roseDetailSubEl: document.getElementById("kab-rose-detail-sub"),
|
||||
roseDetailBodyEl: document.getElementById("kab-rose-detail-body"),
|
||||
};
|
||||
}
|
||||
|
||||
function getRoseDetailElements(elements) {
|
||||
if (!elements) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
detailNameEl: elements.roseDetailNameEl,
|
||||
detailSubEl: elements.roseDetailSubEl,
|
||||
detailBodyEl: elements.roseDetailBodyEl
|
||||
};
|
||||
}
|
||||
|
||||
@@ -286,6 +279,37 @@
|
||||
return window.TarotCardImages.resolveTarotCardImage(cardName);
|
||||
}
|
||||
|
||||
function getSvgImageHref(imageEl) {
|
||||
if (!(imageEl instanceof SVGElement)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return String(
|
||||
imageEl.getAttribute("href")
|
||||
|| imageEl.getAttributeNS("http://www.w3.org/1999/xlink", "href")
|
||||
|| ""
|
||||
).trim();
|
||||
}
|
||||
|
||||
function openTarotLightboxForPath(path, fallbackSrc = "") {
|
||||
const openLightbox = window.TarotUiLightbox?.open;
|
||||
if (typeof openLightbox !== "function") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cardName = String(path?.tarot?.card || "").trim();
|
||||
const src = String(fallbackSrc || resolvePathTarotImage(path) || "").trim();
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fallbackLabel = Number.isFinite(Number(path?.pathNumber))
|
||||
? `Path ${path.pathNumber} tarot card`
|
||||
: "Path tarot card";
|
||||
openLightbox(src, cardName || fallbackLabel);
|
||||
return true;
|
||||
}
|
||||
|
||||
function getPathLabel(path) {
|
||||
const glyph = String(path?.hebrewLetter?.char || "").trim();
|
||||
const pathNumber = Number(path?.pathNumber);
|
||||
@@ -312,6 +336,8 @@
|
||||
return el;
|
||||
}
|
||||
|
||||
// Rosicrucian cross SVG construction lives in app/ui-rosicrucian-cross.js.
|
||||
|
||||
// ─── build the full SVG tree ─────────────────────────────────────────────────
|
||||
function buildTreeSVG(tree) {
|
||||
const svg = svgEl("svg", {
|
||||
@@ -491,14 +517,6 @@
|
||||
return svg;
|
||||
}
|
||||
|
||||
// ─── detail panel helpers ───────────────────────────────────────────────────
|
||||
function metaCard(label, value, wide) {
|
||||
const card = document.createElement("div");
|
||||
card.className = wide ? "planet-meta-card kab-wide-card" : "planet-meta-card";
|
||||
card.innerHTML = `<strong>${label}</strong><p class="planet-text">${value || "—"}</p>`;
|
||||
return card;
|
||||
}
|
||||
|
||||
function normalizeText(value) {
|
||||
return String(value || "").trim().toLowerCase();
|
||||
}
|
||||
@@ -569,114 +587,6 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
function createNavButton(label, eventName, detail) {
|
||||
const btn = document.createElement("button");
|
||||
btn.type = "button";
|
||||
btn.className = "kab-god-link";
|
||||
btn.textContent = `${label} ↗`;
|
||||
btn.addEventListener("click", () => {
|
||||
document.dispatchEvent(new CustomEvent(eventName, { detail }));
|
||||
});
|
||||
return btn;
|
||||
}
|
||||
|
||||
function appendLinkRow(card, buttons) {
|
||||
if (!buttons?.length) return;
|
||||
const row = document.createElement("div");
|
||||
row.className = "kab-god-links";
|
||||
buttons.forEach((button) => row.appendChild(button));
|
||||
card.appendChild(row);
|
||||
}
|
||||
|
||||
function buildPlanetLuminaryCard(planetValue) {
|
||||
const card = metaCard("Planet / Luminary", planetValue);
|
||||
const planetId = resolvePlanetId(planetValue);
|
||||
if (planetId) {
|
||||
appendLinkRow(card, [
|
||||
createNavButton(`View ${PLANET_ID_TO_LABEL[planetId] || planetValue} in Planets`, "nav:planet", { planetId })
|
||||
]);
|
||||
return card;
|
||||
}
|
||||
|
||||
const zodiacId = resolveZodiacId(planetValue);
|
||||
if (zodiacId) {
|
||||
appendLinkRow(card, [
|
||||
createNavButton(`View ${zodiacId.charAt(0).toUpperCase() + zodiacId.slice(1)} in Zodiac`, "nav:zodiac", { signId: zodiacId })
|
||||
]);
|
||||
}
|
||||
return card;
|
||||
}
|
||||
|
||||
function extractMinorRank(attribution) {
|
||||
const match = String(attribution || "").match(/\bthe\s+4\s+(aces|twos|threes|fours|fives|sixes|sevens|eights|nines|tens)\b/i);
|
||||
if (!match) return null;
|
||||
return MINOR_RANK_BY_PLURAL[(match[1] || "").toLowerCase()] || null;
|
||||
}
|
||||
|
||||
function buildMinorTarotNames(attribution) {
|
||||
const rank = extractMinorRank(attribution);
|
||||
if (!rank) return [];
|
||||
return MINOR_SUITS.map((suit) => `${rank} of ${suit}`);
|
||||
}
|
||||
|
||||
function buildTarotAttributionCard(attribution) {
|
||||
const card = metaCard("Tarot Attribution", attribution);
|
||||
const minorCards = buildMinorTarotNames(attribution);
|
||||
if (minorCards.length) {
|
||||
appendLinkRow(card, minorCards.map((cardName) =>
|
||||
createNavButton(cardName, "nav:tarot-trump", { cardName })
|
||||
));
|
||||
}
|
||||
return card;
|
||||
}
|
||||
|
||||
function buildAstrologyCard(astrology) {
|
||||
const astroText = astrology ? `${astrology.name} (${astrology.type})` : "—";
|
||||
const card = metaCard("Astrology", astroText);
|
||||
if (astrology?.type === "planet") {
|
||||
const planetId = resolvePlanetId(astrology.name);
|
||||
if (planetId) {
|
||||
appendLinkRow(card, [
|
||||
createNavButton(`View ${PLANET_ID_TO_LABEL[planetId] || astrology.name} in Planets`, "nav:planet", { planetId })
|
||||
]);
|
||||
}
|
||||
} else if (astrology?.type === "zodiac") {
|
||||
const signId = resolveZodiacId(astrology.name);
|
||||
if (signId) {
|
||||
appendLinkRow(card, [
|
||||
createNavButton(`View ${signId.charAt(0).toUpperCase() + signId.slice(1)} in Zodiac`, "nav:zodiac", { signId })
|
||||
]);
|
||||
}
|
||||
}
|
||||
return card;
|
||||
}
|
||||
|
||||
function buildConnectsCard(path, fromName, toName) {
|
||||
const card = metaCard("Connects", `${fromName} → ${toName}`);
|
||||
appendLinkRow(card, [
|
||||
createNavButton(`View ${fromName}`, "nav:kabbalah-path", { pathNo: Number(path.connects.from) }),
|
||||
createNavButton(`View ${toName}`, "nav:kabbalah-path", { pathNo: Number(path.connects.to) })
|
||||
]);
|
||||
return card;
|
||||
}
|
||||
|
||||
function buildHebrewLetterCard(letter) {
|
||||
const label = `${letter.char || ""} ${letter.transliteration || ""} — "${letter.meaning || ""}" (${letter.letterType || ""})`;
|
||||
const card = metaCard("Hebrew Letter", label);
|
||||
const hebrewLetterId = resolveHebrewLetterId(letter.transliteration || letter.char || "");
|
||||
|
||||
if (hebrewLetterId) {
|
||||
appendLinkRow(card, [
|
||||
createNavButton(`View ${letter.transliteration || letter.char || "Letter"} in Alphabet`, "nav:alphabet", {
|
||||
alphabet: "hebrew",
|
||||
hebrewLetterId
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
function findPathByHebrewToken(tree, hebrewToken) {
|
||||
const canonicalToken = HEBREW_LETTER_ALIASES[normalizeLetterToken(hebrewToken)] || normalizeLetterToken(hebrewToken);
|
||||
if (!canonicalToken) {
|
||||
@@ -691,200 +601,27 @@
|
||||
}) || null;
|
||||
}
|
||||
|
||||
function buildFourWorldsCard(tree, activeLetterToken = "") {
|
||||
const activeToken = HEBREW_LETTER_ALIASES[normalizeLetterToken(activeLetterToken)] || normalizeLetterToken(activeLetterToken);
|
||||
const worldLayers = Array.isArray(state.fourWorldLayers) && state.fourWorldLayers.length
|
||||
? state.fourWorldLayers
|
||||
: DEFAULT_FOUR_QABALISTIC_WORLD_LAYERS;
|
||||
|
||||
const card = document.createElement("div");
|
||||
card.className = "planet-meta-card kab-wide-card";
|
||||
|
||||
const title = document.createElement("strong");
|
||||
title.textContent = "Four Qabalistic Worlds & Soul Layers";
|
||||
card.appendChild(title);
|
||||
|
||||
const stack = document.createElement("div");
|
||||
stack.className = "cal-item-stack";
|
||||
|
||||
worldLayers.forEach((layer) => {
|
||||
const row = document.createElement("div");
|
||||
row.className = "cal-item-row";
|
||||
|
||||
const isActive = Boolean(activeToken) && activeToken === layer.hebrewToken;
|
||||
|
||||
const head = document.createElement("div");
|
||||
head.className = "cal-item-head";
|
||||
head.innerHTML = `
|
||||
<span class="cal-item-name">${layer.slot}: ${layer.letterChar} — ${layer.world}</span>
|
||||
<span class="planet-list-meta">${layer.soulLayer}</span>
|
||||
`;
|
||||
row.appendChild(head);
|
||||
|
||||
const worldLine = document.createElement("div");
|
||||
worldLine.className = "planet-text";
|
||||
worldLine.textContent = `${layer.worldLayer} · ${layer.worldDescription}`;
|
||||
row.appendChild(worldLine);
|
||||
|
||||
const soulLine = document.createElement("div");
|
||||
soulLine.className = "planet-text";
|
||||
soulLine.textContent = `${layer.soulLayer} — ${layer.soulTitle}: ${layer.soulDescription}`;
|
||||
row.appendChild(soulLine);
|
||||
|
||||
const buttonRow = [];
|
||||
const hebrewLetterId = resolveHebrewLetterId(layer.hebrewToken);
|
||||
if (hebrewLetterId) {
|
||||
buttonRow.push(
|
||||
createNavButton(`View ${layer.letterChar} in Alphabet`, "nav:alphabet", {
|
||||
alphabet: "hebrew",
|
||||
hebrewLetterId
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const linkedPath = findPathByHebrewToken(tree, layer.hebrewToken);
|
||||
if (linkedPath?.pathNumber != null) {
|
||||
buttonRow.push(
|
||||
createNavButton(`View Path ${linkedPath.pathNumber}`, "nav:kabbalah-path", { pathNo: Number(linkedPath.pathNumber) })
|
||||
);
|
||||
}
|
||||
|
||||
appendLinkRow(row, buttonRow);
|
||||
|
||||
if (isActive) {
|
||||
row.style.borderColor = "#818cf8";
|
||||
}
|
||||
|
||||
stack.appendChild(row);
|
||||
});
|
||||
|
||||
card.appendChild(stack);
|
||||
return card;
|
||||
}
|
||||
|
||||
function splitCorrespondenceNames(value) {
|
||||
return String(value || "")
|
||||
.split(/,|;|·|\/|\bor\b|\band\b|\+/i)
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function uniqueNames(values) {
|
||||
const seen = new Set();
|
||||
const output = [];
|
||||
values.forEach((name) => {
|
||||
const key = String(name || "").toLowerCase();
|
||||
if (seen.has(key)) return;
|
||||
seen.add(key);
|
||||
output.push(name);
|
||||
});
|
||||
return output;
|
||||
}
|
||||
|
||||
function godLinksCard(label, names, pathNo, metaText) {
|
||||
const card = document.createElement("div");
|
||||
card.className = "planet-meta-card";
|
||||
|
||||
const title = document.createElement("strong");
|
||||
title.textContent = label;
|
||||
card.appendChild(title);
|
||||
|
||||
if (metaText) {
|
||||
const meta = document.createElement("p");
|
||||
meta.className = "planet-text kab-god-meta";
|
||||
meta.textContent = metaText;
|
||||
card.appendChild(meta);
|
||||
}
|
||||
|
||||
const row = document.createElement("div");
|
||||
row.className = "kab-god-links";
|
||||
|
||||
names.forEach((name) => {
|
||||
const btn = document.createElement("button");
|
||||
btn.type = "button";
|
||||
btn.className = "kab-god-link";
|
||||
btn.textContent = name;
|
||||
btn.addEventListener("click", () => {
|
||||
document.dispatchEvent(new CustomEvent("nav:gods", {
|
||||
detail: { godName: name, pathNo: Number(pathNo) }
|
||||
}));
|
||||
});
|
||||
row.appendChild(btn);
|
||||
});
|
||||
|
||||
card.appendChild(row);
|
||||
return card;
|
||||
function getDetailRenderContext(tree, elements, extra = {}) {
|
||||
return {
|
||||
tree,
|
||||
elements,
|
||||
godsData: state.godsData,
|
||||
fourWorldLayers: state.fourWorldLayers,
|
||||
resolvePlanetId,
|
||||
resolveZodiacId,
|
||||
resolveHebrewLetterId,
|
||||
findPathByHebrewToken,
|
||||
...extra
|
||||
};
|
||||
}
|
||||
|
||||
function clearHighlights() {
|
||||
document.querySelectorAll(".kab-node, .kab-node-glow")
|
||||
.forEach(el => el.classList.remove("kab-node-active"));
|
||||
document.querySelectorAll(".kab-path-hit, .kab-path-line, .kab-path-lbl, .kab-path-tarot")
|
||||
document.querySelectorAll(".kab-path-hit, .kab-path-line, .kab-path-lbl, .kab-path-tarot, .kab-rose-petal")
|
||||
.forEach(el => el.classList.remove("kab-path-active"));
|
||||
}
|
||||
|
||||
// ─── helper: append divine correspondences from gods.json ─────────────────────
|
||||
function appendGodsCards(pathNo, elements) {
|
||||
const gd = state.godsData[String(pathNo)];
|
||||
if (!gd) return;
|
||||
|
||||
const hasAny = gd.greek || gd.roman || gd.egyptian || gd.egyptianPractical
|
||||
|| gd.elohim || gd.archangel || gd.angelicOrder;
|
||||
if (!hasAny) return;
|
||||
|
||||
const sep = document.createElement("div");
|
||||
sep.className = "planet-meta-card kab-wide-card";
|
||||
sep.innerHTML = `<strong style="color:#a1a1aa;font-size:11px;text-transform:uppercase;letter-spacing:.05em">Divine Correspondences</strong>`;
|
||||
elements.detailBodyEl.appendChild(sep);
|
||||
|
||||
const greekNames = uniqueNames(splitCorrespondenceNames(gd.greek));
|
||||
const romanNames = uniqueNames(splitCorrespondenceNames(gd.roman));
|
||||
const egyptNames = uniqueNames([
|
||||
...splitCorrespondenceNames(gd.egyptianPractical),
|
||||
...splitCorrespondenceNames(gd.egyptian)
|
||||
]);
|
||||
|
||||
if (greekNames.length) {
|
||||
elements.detailBodyEl.appendChild(godLinksCard("Greek", greekNames, pathNo));
|
||||
}
|
||||
if (romanNames.length) {
|
||||
elements.detailBodyEl.appendChild(godLinksCard("Roman", romanNames, pathNo));
|
||||
}
|
||||
if (egyptNames.length) {
|
||||
elements.detailBodyEl.appendChild(godLinksCard("Egyptian", egyptNames, pathNo));
|
||||
}
|
||||
|
||||
if (gd.elohim) {
|
||||
const g = gd.elohim;
|
||||
const meta = `${g.hebrew}${g.meaning ? " — " + g.meaning : ""}`;
|
||||
elements.detailBodyEl.appendChild(godLinksCard(
|
||||
"God Name",
|
||||
uniqueNames(splitCorrespondenceNames(g.transliteration)),
|
||||
pathNo,
|
||||
meta
|
||||
));
|
||||
}
|
||||
if (gd.archangel) {
|
||||
const a = gd.archangel;
|
||||
const meta = `${a.hebrew}`;
|
||||
elements.detailBodyEl.appendChild(godLinksCard(
|
||||
"Archangel",
|
||||
uniqueNames(splitCorrespondenceNames(a.transliteration)),
|
||||
pathNo,
|
||||
meta
|
||||
));
|
||||
}
|
||||
if (gd.angelicOrder) {
|
||||
const o = gd.angelicOrder;
|
||||
elements.detailBodyEl.appendChild(metaCard(
|
||||
"Angelic Order",
|
||||
`${o.hebrew} ${o.transliteration}${o.meaning ? " — " + o.meaning : ""}`
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ─── render sephira detail ───────────────────────────────────────────────────
|
||||
function renderSephiraDetail(seph, tree, elements) {
|
||||
state.selectedSephiraNumber = Number(seph?.number);
|
||||
state.selectedPathNumber = null;
|
||||
@@ -893,53 +630,14 @@
|
||||
document.querySelectorAll(`.kab-node[data-sephira="${seph.number}"], .kab-node-glow[data-sephira="${seph.number}"]`)
|
||||
.forEach(el => el.classList.add("kab-node-active"));
|
||||
|
||||
elements.detailNameEl.textContent = `${seph.number} · ${seph.name}`;
|
||||
elements.detailSubEl.textContent =
|
||||
[seph.nameHebrew, seph.translation, seph.planet].filter(Boolean).join(" · ");
|
||||
|
||||
elements.detailBodyEl.innerHTML = "";
|
||||
elements.detailBodyEl.appendChild(buildFourWorldsCard(tree));
|
||||
elements.detailBodyEl.appendChild(buildPlanetLuminaryCard(seph.planet));
|
||||
elements.detailBodyEl.appendChild(metaCard("Intelligence", seph.intelligence));
|
||||
elements.detailBodyEl.appendChild(buildTarotAttributionCard(seph.tarot));
|
||||
|
||||
if (seph.description) {
|
||||
elements.detailBodyEl.appendChild(
|
||||
metaCard(seph.name, seph.description, true)
|
||||
);
|
||||
if (typeof kabbalahDetailUi.renderSephiraDetail === "function") {
|
||||
kabbalahDetailUi.renderSephiraDetail(getDetailRenderContext(tree, elements, {
|
||||
seph,
|
||||
onPathSelect: (path) => renderPathDetail(path, tree, elements)
|
||||
}));
|
||||
}
|
||||
|
||||
// Quick-access chips for connected paths
|
||||
const connected = tree.paths.filter(
|
||||
p => p.connects.from === seph.number || p.connects.to === seph.number
|
||||
);
|
||||
if (connected.length) {
|
||||
const card = document.createElement("div");
|
||||
card.className = "planet-meta-card kab-wide-card";
|
||||
const chips = connected.map(p =>
|
||||
`<span class="kab-chip" data-path="${p.pathNumber}" role="button" tabindex="0" title="Path ${p.pathNumber}: ${p.tarot?.card || ""}">`
|
||||
+ `${p.hebrewLetter?.char || ""} <span class="kab-chip-sub">${p.pathNumber}</span>`
|
||||
+ `</span>`
|
||||
).join("");
|
||||
card.innerHTML = `<strong>Connected Paths</strong><div class="kab-chips">${chips}</div>`;
|
||||
elements.detailBodyEl.appendChild(card);
|
||||
|
||||
card.querySelectorAll(".kab-chip[data-path]").forEach(chip => {
|
||||
const handler = () => {
|
||||
const path = tree.paths.find(p => p.pathNumber === Number(chip.dataset.path));
|
||||
if (path) renderPathDetail(path, tree, elements);
|
||||
};
|
||||
chip.addEventListener("click", handler);
|
||||
chip.addEventListener("keydown", e => {
|
||||
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); handler(); }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
appendGodsCards(seph.number, elements);
|
||||
}
|
||||
|
||||
// ─── render path detail ──────────────────────────────────────────────────────
|
||||
function renderPathDetail(path, tree, elements) {
|
||||
state.selectedPathNumber = Number(path?.pathNumber);
|
||||
state.selectedSephiraNumber = null;
|
||||
@@ -948,70 +646,30 @@
|
||||
document.querySelectorAll(`[data-path="${path.pathNumber}"]`)
|
||||
.forEach(el => el.classList.add("kab-path-active"));
|
||||
|
||||
const letter = path.hebrewLetter || {};
|
||||
const fromName = tree.sephiroth.find(s => s.number === path.connects.from)?.name || path.connects.from;
|
||||
const toName = tree.sephiroth.find(s => s.number === path.connects.to)?.name || path.connects.to;
|
||||
const astro = path.astrology ? `${path.astrology.name} (${path.astrology.type})` : "—";
|
||||
const tarotStr = path.tarot?.card
|
||||
? `${path.tarot.card}${path.tarot.trumpNumber != null ? " · Trump " + path.tarot.trumpNumber : ""}`
|
||||
: "—";
|
||||
|
||||
elements.detailNameEl.textContent =
|
||||
`Path ${path.pathNumber} · ${letter.char || ""} ${letter.transliteration || ""}`;
|
||||
elements.detailSubEl.textContent = [path.tarot?.card, astro].filter(Boolean).join(" · ");
|
||||
|
||||
elements.detailBodyEl.innerHTML = "";
|
||||
elements.detailBodyEl.appendChild(buildFourWorldsCard(tree, letter.transliteration || letter.char || ""));
|
||||
elements.detailBodyEl.appendChild(buildConnectsCard(path, fromName, toName));
|
||||
elements.detailBodyEl.appendChild(buildHebrewLetterCard(letter));
|
||||
elements.detailBodyEl.appendChild(buildAstrologyCard(path.astrology));
|
||||
|
||||
// Tarot card — clickable if a trump card is associated
|
||||
const tarotMetaCard = document.createElement("div");
|
||||
tarotMetaCard.className = "planet-meta-card";
|
||||
const tarotLabel = document.createElement("strong");
|
||||
tarotLabel.textContent = "Tarot";
|
||||
tarotMetaCard.appendChild(tarotLabel);
|
||||
if (path.tarot?.card && path.tarot.trumpNumber != null) {
|
||||
const tarotBtn = document.createElement("button");
|
||||
tarotBtn.type = "button";
|
||||
tarotBtn.className = "kab-tarot-link";
|
||||
tarotBtn.textContent = `${path.tarot.card} · Trump ${path.tarot.trumpNumber}`;
|
||||
tarotBtn.title = "Open in Tarot section";
|
||||
tarotBtn.addEventListener("click", () => {
|
||||
document.dispatchEvent(new CustomEvent("kab:view-trump", {
|
||||
detail: { trumpNumber: path.tarot.trumpNumber }
|
||||
}));
|
||||
});
|
||||
tarotMetaCard.appendChild(tarotBtn);
|
||||
} else {
|
||||
const tarotP = document.createElement("p");
|
||||
tarotP.className = "planet-text";
|
||||
tarotP.textContent = tarotStr || "—";
|
||||
tarotMetaCard.appendChild(tarotP);
|
||||
if (typeof kabbalahDetailUi.renderPathDetail === "function") {
|
||||
kabbalahDetailUi.renderPathDetail(getDetailRenderContext(tree, elements, {
|
||||
path,
|
||||
activeHebrewToken: normalizeLetterToken(path?.hebrewLetter?.transliteration || path?.hebrewLetter?.char || "")
|
||||
}));
|
||||
}
|
||||
elements.detailBodyEl.appendChild(tarotMetaCard);
|
||||
|
||||
elements.detailBodyEl.appendChild(metaCard("Intelligence", path.intelligence));
|
||||
elements.detailBodyEl.appendChild(metaCard("Pillar", path.pillar));
|
||||
|
||||
if (path.description) {
|
||||
const desc = document.createElement("div");
|
||||
desc.className = "planet-meta-card kab-wide-card";
|
||||
desc.innerHTML =
|
||||
`<strong>Path ${path.pathNumber} — Sefer Yetzirah</strong>`
|
||||
+ `<p class="planet-text">${path.description.replace(/\n/g, "<br><br>")}</p>`;
|
||||
elements.detailBodyEl.appendChild(desc);
|
||||
}
|
||||
|
||||
appendGodsCards(path.pathNumber, elements);
|
||||
}
|
||||
|
||||
function bindTreeInteractions(svg, tree, elements) {
|
||||
// Delegate clicks via element's own data attributes
|
||||
svg.addEventListener("click", e => {
|
||||
const sephNum = e.target.dataset?.sephira;
|
||||
const pathNum = e.target.dataset?.path;
|
||||
const clickTarget = e.target instanceof Element ? e.target : null;
|
||||
const sephNum = clickTarget?.dataset?.sephira;
|
||||
const pathNum = clickTarget?.dataset?.path;
|
||||
|
||||
if (pathNum != null && clickTarget?.classList?.contains("kab-path-tarot")) {
|
||||
const p = tree.paths.find(x => x.pathNumber === Number(pathNum));
|
||||
if (p) {
|
||||
openTarotLightboxForPath(p, getSvgImageHref(clickTarget));
|
||||
renderPathDetail(p, tree, elements);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (sephNum != null) {
|
||||
const s = tree.sephiroth.find(x => x.number === Number(sephNum));
|
||||
if (s) renderSephiraDetail(s, tree, elements);
|
||||
@@ -1027,7 +685,12 @@
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
const p = tree.paths.find(x => x.pathNumber === Number(el.dataset.path));
|
||||
if (p) renderPathDetail(p, tree, elements);
|
||||
if (p) {
|
||||
if (el.classList.contains("kab-path-tarot")) {
|
||||
openTarotLightboxForPath(p, getSvgImageHref(el));
|
||||
}
|
||||
renderPathDetail(p, tree, elements);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1044,6 +707,94 @@
|
||||
});
|
||||
}
|
||||
|
||||
function bindRoseCrossInteractions(svg, tree, roseElements) {
|
||||
if (!svg || !roseElements?.detailBodyEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const openPathFromTarget = (targetEl) => {
|
||||
if (!(targetEl instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const petal = targetEl.closest(".kab-rose-petal[data-path]");
|
||||
if (!(petal instanceof SVGElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pathNumber = Number(petal.dataset.path);
|
||||
if (!Number.isFinite(pathNumber)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const path = tree.paths.find((entry) => entry.pathNumber === pathNumber);
|
||||
if (path) {
|
||||
renderPathDetail(path, tree, roseElements);
|
||||
}
|
||||
};
|
||||
|
||||
svg.addEventListener("click", (event) => {
|
||||
openPathFromTarget(event.target);
|
||||
});
|
||||
|
||||
svg.querySelectorAll(".kab-rose-petal[data-path]").forEach((petal) => {
|
||||
petal.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
openPathFromTarget(petal);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderRoseLandingIntro(roseElements) {
|
||||
if (typeof kabbalahDetailUi.renderRoseLandingIntro === "function") {
|
||||
kabbalahDetailUi.renderRoseLandingIntro(roseElements);
|
||||
}
|
||||
}
|
||||
|
||||
function renderRoseCross(elements) {
|
||||
if (!state.tree || !elements?.roseCrossContainerEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const roseElements = getRoseDetailElements(elements);
|
||||
if (!roseElements?.detailBodyEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const roseBuilder = window.KabbalahRosicrucianCross?.buildRosicrucianCrossSVG;
|
||||
if (typeof roseBuilder !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
const roseSvg = roseBuilder(state.tree);
|
||||
elements.roseCrossContainerEl.innerHTML = "";
|
||||
elements.roseCrossContainerEl.appendChild(roseSvg);
|
||||
bindRoseCrossInteractions(roseSvg, state.tree, roseElements);
|
||||
}
|
||||
|
||||
function renderRoseCurrentSelection(elements) {
|
||||
if (!state.tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
const roseElements = getRoseDetailElements(elements);
|
||||
if (!roseElements?.detailBodyEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Number.isFinite(Number(state.selectedPathNumber))) {
|
||||
const selectedPath = state.tree.paths.find((entry) => entry.pathNumber === Number(state.selectedPathNumber));
|
||||
if (selectedPath) {
|
||||
renderPathDetail(selectedPath, state.tree, roseElements);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
renderRoseLandingIntro(roseElements);
|
||||
}
|
||||
|
||||
function renderTree(elements) {
|
||||
if (!state.tree || !elements?.treeContainerEl) {
|
||||
return;
|
||||
@@ -1119,6 +870,8 @@
|
||||
|
||||
renderTree(elements);
|
||||
renderCurrentSelection(elements);
|
||||
renderRoseCross(elements);
|
||||
renderRoseCurrentSelection(elements);
|
||||
}
|
||||
|
||||
function selectPathByNumber(pathNumber) {
|
||||
|
||||
Reference in New Issue
Block a user