updated relationship display in cycle details to use inline links instead of alpha nav buttons, and added related cycle links to planet details; added element display to astrology alphabet details; updated decan range display in calendar detail panels; updated tarot card detail script to latest version; added element script to index.html

This commit is contained in:
2026-04-24 04:25:27 -07:00
parent e18ec31cf9
commit 7cdcdb4456
12 changed files with 473 additions and 109 deletions
+143 -40
View File
@@ -34,6 +34,19 @@
return String(signId || "").trim().toLowerCase();
}
function formatPaddedDegreeRange(startDegree, endDegree) {
const start = Number(startDegree);
const end = Number(endDegree);
if (!Number.isFinite(start) || !Number.isFinite(end)) {
return "";
}
const normalizedStart = Math.trunc(start);
const normalizedEnd = Math.trunc(end) - (Math.trunc(end) - Math.trunc(start) === 10 ? 1 : 0);
return `(${String(normalizedStart).padStart(2, "0")}°-${String(normalizedEnd).padStart(2, "0")}°)`;
}
function buildDecanSummaryRelations(relations) {
const decanRelations = (relations || []).filter((relation) => relation?.type === "decan");
const signWindowRelations = (relations || []).filter((relation) => relation?.type === "signWindow");
@@ -98,9 +111,7 @@
? String(getDisplayCardName?.(decanCardName) || decanCardName).trim()
: "";
const signLabel = `${signSymbol} ${signName}`.replace(/\s+/g, " ").trim();
const degreeLabel = Number.isFinite(startDegree) && Number.isFinite(endDegree)
? `(${startDegree}°-${endDegree}°)`
: "";
const degreeLabel = formatPaddedDegreeRange(startDegree, endDegree);
const dateLabel = normalizeInlineDateRange(dateRange);
const summaryParts = [
rulerLabel,
@@ -138,9 +149,7 @@
.map((entry) => String(getDisplayCardName?.(entry?.data?.cardName) || entry?.data?.cardName || "").trim())
.filter(Boolean))];
const signLabel = `${signSymbol} ${signName}`.replace(/\s+/g, " ").trim();
const degreeLabel = Number.isFinite(startDegree) && Number.isFinite(endDegree)
? `(${startDegree}°-${endDegree}°)`
: "";
const degreeLabel = formatPaddedDegreeRange(startDegree, endDegree);
const dateLabel = normalizeInlineDateRange(dateRange);
const summaryParts = [
cardLabels.join(", "),
@@ -181,6 +190,47 @@
});
}
function createInlineButton(label, eventName, detail) {
const button = document.createElement("button");
button.type = "button";
button.className = "detail-inline-link";
button.textContent = String(label || "—");
button.addEventListener("click", () => {
document.dispatchEvent(new CustomEvent(eventName, { detail }));
});
return button;
}
function createInlineValue(parts) {
const inline = document.createElement("div");
inline.className = "planet-text detail-inline-value";
(Array.isArray(parts) ? parts : []).forEach((part) => {
if (part instanceof Node) {
inline.appendChild(part);
return;
}
const text = String(part || "");
if (text) {
inline.appendChild(document.createTextNode(text));
}
});
return inline;
}
function resolvePlanetId(value) {
const token = String(value || "").trim().toLowerCase();
if (!token) {
return "";
}
if (token === "sun") return "sol";
if (token === "moon") return "luna";
return token;
}
function collectDetailRelations(card) {
const allRelations = (card.relations || [])
.map((relation, index) => normalizeRelationObject(relation, index))
@@ -447,63 +497,116 @@
const letter = kabPath.hebrewLetter || {};
const fromName = kabTree.sephiroth.find((seph) => seph.number === kabPath.connects.from)?.name || kabPath.connects.from;
const toName = kabTree.sephiroth.find((seph) => seph.number === kabPath.connects.to)?.name || kabPath.connects.to;
const astro = kabPath.astrology ? `${kabPath.astrology.name} (${kabPath.astrology.type})` : "";
const astrologyType = String(kabPath.astrology?.type || "").trim().toLowerCase();
const astrologyName = String(kabPath.astrology?.name || "").trim();
kabPathEl.innerHTML = `
<strong>Kabbalah Tree &#8212; Path ${kabPath.pathNumber}</strong>
<strong>Kabbalah Tree</strong>
<div class="tarot-kab-path-row">
<span class="tarot-kab-letter" title="${letter.transliteration || ""}">${letter.char || ""}</span>
<span class="tarot-kab-meta">
<span class="tarot-kab-name">${letter.transliteration || ""} &mdash; &ldquo;${letter.meaning || ""}&rdquo; &middot; ${letter.letterType || ""}</span>
<span class="tarot-kab-connects">${fromName} &rarr; ${toName}${astro ? " &middot; " + astro : ""}</span>
<span class="tarot-kab-name"></span>
<span class="tarot-kab-connects"></span>
</span>
</div>`;
const btn = document.createElement("button");
btn.type = "button";
btn.className = "detail-inline-link";
btn.textContent = `Path ${kabPath.pathNumber}`;
btn.addEventListener("click", () => {
document.dispatchEvent(new CustomEvent("tarot:view-kab-path", {
detail: { pathNumber: kabPath.pathNumber }
const pathNameEl = kabPathEl.querySelector(".tarot-kab-name");
if (pathNameEl) {
pathNameEl.appendChild(createInlineButton(`Path ${kabPath.pathNumber}`, "nav:kabbalah-path", {
pathNo: kabPath.pathNumber
}));
});
const inline = document.createElement("div");
inline.className = "planet-text detail-inline-value";
inline.appendChild(document.createTextNode("Kabbalah "));
inline.appendChild(btn);
kabPathEl.appendChild(inline);
pathNameEl.appendChild(document.createTextNode(`${letter.transliteration || ""}`));
if (letter.meaning) {
pathNameEl.appendChild(document.createTextNode(` - \"${letter.meaning}\"`));
}
if (letter.letterType) {
pathNameEl.appendChild(document.createTextNode(` - ${letter.letterType}`));
}
}
const connectsEl = kabPathEl.querySelector(".tarot-kab-connects");
if (connectsEl) {
connectsEl.appendChild(createInlineButton(fromName, "nav:kabbalah-path", {
pathNo: kabPath.connects.from
}));
connectsEl.appendChild(document.createTextNode(" → "));
connectsEl.appendChild(createInlineButton(toName, "nav:kabbalah-path", {
pathNo: kabPath.connects.to
}));
if (astrologyName) {
connectsEl.appendChild(document.createTextNode(" · "));
if (astrologyType === "planet") {
connectsEl.appendChild(createInlineButton(astrologyName, "nav:planet", {
planetId: resolvePlanetId(astrologyName)
}));
} else if (astrologyType === "zodiac") {
connectsEl.appendChild(createInlineButton(astrologyName, "nav:zodiac", {
signId: astrologyName.toLowerCase()
}));
} else {
connectsEl.appendChild(document.createTextNode(`${astrologyName} (${astrologyType || "astrology"})`));
}
}
}
const letterId = String(letter.transliteration || "").trim().toLowerCase();
if (letterId) {
kabPathEl.appendChild(createInlineValue([
"Hebrew ",
createInlineButton(`${letter.char || ""} ${letter.transliteration || letterId}`.trim(), "nav:alphabet", {
alphabet: "hebrew",
hebrewLetterId: letterId
})
]));
}
kabPathEl.hidden = false;
} else if (kabSeph) {
const hebrewName = kabSeph.nameHebrew ? ` (${kabSeph.nameHebrew})` : "";
const translation = kabSeph.translation ? `${kabSeph.translation}` : "";
const planetInfo = kabSeph.planet || "";
const tarotInfo = kabSeph.tarot ? ` · ${kabSeph.tarot}` : "";
const resolvedPlanetId = resolvePlanetId(planetInfo);
kabPathEl.innerHTML = `
<strong>Kabbalah Tree &#8212; Sephirah ${kabSeph.number}</strong>
<strong>Kabbalah Tree</strong>
<div class="tarot-kab-path-row">
<span class="tarot-kab-letter" title="${kabSeph.name || ""}">${kabSeph.number}</span>
<span class="tarot-kab-letter" title="${kabSeph.name || ""}"></span>
<span class="tarot-kab-meta">
<span class="tarot-kab-name">${kabSeph.name || ""}${hebrewName}${translation}</span>
<span class="tarot-kab-connects">${planetInfo}${tarotInfo}</span>
<span class="tarot-kab-name"></span>
<span class="tarot-kab-connects"></span>
</span>
</div>`;
const btn = document.createElement("button");
btn.type = "button";
btn.className = "detail-inline-link";
btn.textContent = `Sephirah ${kabSeph.number}`;
btn.addEventListener("click", () => {
document.dispatchEvent(new CustomEvent("tarot:view-kab-path", {
detail: { pathNumber: kabSeph.number }
const sephirahLetterEl = kabPathEl.querySelector(".tarot-kab-letter");
if (sephirahLetterEl) {
sephirahLetterEl.appendChild(createInlineButton(`${kabSeph.number}`, "nav:kabbalah-path", {
pathNo: kabSeph.number
}));
});
const inline = document.createElement("div");
inline.className = "planet-text detail-inline-value";
inline.appendChild(document.createTextNode("Kabbalah "));
inline.appendChild(btn);
kabPathEl.appendChild(inline);
}
const sephirahNameEl = kabPathEl.querySelector(".tarot-kab-name");
if (sephirahNameEl) {
sephirahNameEl.appendChild(createInlineButton(`Sephirah ${kabSeph.number}${kabSeph.name || "Sephirah"}${hebrewName}${translation}`, "nav:kabbalah-path", {
pathNo: kabSeph.number
}));
}
const sephirahConnectsEl = kabPathEl.querySelector(".tarot-kab-connects");
if (sephirahConnectsEl) {
if (resolvedPlanetId) {
sephirahConnectsEl.appendChild(createInlineButton(planetInfo, "nav:planet", { planetId: resolvedPlanetId }));
} else if (planetInfo) {
sephirahConnectsEl.appendChild(document.createTextNode(planetInfo));
}
if (tarotInfo) {
if (sephirahConnectsEl.childNodes.length) {
sephirahConnectsEl.appendChild(document.createTextNode(" · "));
}
sephirahConnectsEl.appendChild(document.createTextNode(String(kabSeph.tarot || "")));
}
}
kabPathEl.hidden = false;
} else {
kabPathEl.hidden = true;