refactoring
This commit is contained in:
615
app/ui-cube.js
615
app/ui-cube.js
@@ -119,6 +119,7 @@
|
||||
above: { x: -90, y: 0 },
|
||||
below: { x: 90, y: 0 }
|
||||
};
|
||||
const cubeDetailUi = window.CubeDetailUi || {};
|
||||
|
||||
function getElements() {
|
||||
return {
|
||||
@@ -655,6 +656,22 @@
|
||||
return window.TarotCardImages.resolveTarotCardImage(name) || null;
|
||||
}
|
||||
|
||||
function openTarotCardLightbox(cardName, fallbackSrc = "", fallbackLabel = "") {
|
||||
const openLightbox = window.TarotUiLightbox?.open;
|
||||
if (typeof openLightbox !== "function") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const src = toDisplayText(fallbackSrc) || resolveCardImageUrl(cardName);
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const label = toDisplayText(cardName) || toDisplayText(fallbackLabel) || "Tarot card";
|
||||
openLightbox(src, label);
|
||||
return true;
|
||||
}
|
||||
|
||||
function applyPlacement(placement) {
|
||||
const fallbackWallId = normalizeId(getWalls()[0]?.id);
|
||||
const nextWallId = normalizeId(placement?.wallId || placement?.wall?.id || state.selectedWallId || fallbackWallId);
|
||||
@@ -678,55 +695,10 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
function createMetaCard(title, bodyContent) {
|
||||
const card = document.createElement("div");
|
||||
card.className = "planet-meta-card";
|
||||
|
||||
const titleEl = document.createElement("strong");
|
||||
titleEl.textContent = title;
|
||||
card.appendChild(titleEl);
|
||||
|
||||
if (typeof bodyContent === "string") {
|
||||
const bodyEl = document.createElement("p");
|
||||
bodyEl.className = "planet-text";
|
||||
bodyEl.textContent = bodyContent;
|
||||
card.appendChild(bodyEl);
|
||||
} else if (bodyContent instanceof Node) {
|
||||
card.appendChild(bodyContent);
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
function createNavButton(label, eventName, detail) {
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.className = "kab-god-link";
|
||||
button.textContent = `${label} ↗`;
|
||||
button.addEventListener("click", () => {
|
||||
document.dispatchEvent(new CustomEvent(eventName, { detail }));
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
||||
function toDisplayText(value) {
|
||||
return String(value ?? "").trim();
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function toDetailValueMarkup(value) {
|
||||
const text = toDisplayText(value);
|
||||
return text ? escapeHtml(text) : '<span class="cube-missing-value">!</span>';
|
||||
}
|
||||
|
||||
function renderFaceSvg(containerEl, walls) {
|
||||
if (!containerEl) {
|
||||
return;
|
||||
@@ -819,7 +791,9 @@
|
||||
defs.appendChild(clipPath);
|
||||
|
||||
const cardW = 40, cardH = 60;
|
||||
const wallTarotCard = getWallTarotCard(wall);
|
||||
const cardImg = document.createElementNS(svgNS, "image");
|
||||
cardImg.setAttribute("class", "cube-tarot-image cube-face-card");
|
||||
cardImg.setAttribute("href", cardUrl);
|
||||
cardImg.setAttribute("x", String((faceGlyphAnchor.x - cardW / 2).toFixed(2)));
|
||||
cardImg.setAttribute("y", String((faceGlyphAnchor.y - cardH / 2).toFixed(2)));
|
||||
@@ -828,13 +802,19 @@
|
||||
cardImg.setAttribute("clip-path", `url(#${clipId})`);
|
||||
cardImg.setAttribute("role", "button");
|
||||
cardImg.setAttribute("tabindex", "0");
|
||||
cardImg.setAttribute("aria-label", `Cube wall ${wall?.name || wallId}`);
|
||||
cardImg.setAttribute("aria-label", `Open ${wallTarotCard || (wall?.name || wallId)} card image`);
|
||||
cardImg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
||||
cardImg.addEventListener("click", selectWall);
|
||||
cardImg.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
selectWall();
|
||||
openTarotCardLightbox(wallTarotCard, cardUrl, `${wall?.name || wallId} wall tarot card`);
|
||||
});
|
||||
cardImg.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
selectWall();
|
||||
openTarotCardLightbox(wallTarotCard, cardUrl, `${wall?.name || wallId} wall tarot card`);
|
||||
}
|
||||
});
|
||||
svg.appendChild(cardImg);
|
||||
@@ -922,16 +902,40 @@
|
||||
const labelX = ((from.x + to.x) / 2) + (perpX * shift);
|
||||
const labelY = ((from.y + to.y) / 2) + (perpY * shift);
|
||||
|
||||
const selectConnector = () => {
|
||||
state.selectedNodeType = "connector";
|
||||
state.selectedConnectorId = connectorId;
|
||||
render(getElements());
|
||||
};
|
||||
|
||||
if (state.markerDisplayMode === "tarot" && connectorCardUrl) {
|
||||
const cardW = 18;
|
||||
const cardH = 27;
|
||||
const connectorTarotCard = getConnectorTarotCard(connector);
|
||||
const connectorImg = document.createElementNS(svgNS, "image");
|
||||
connectorImg.setAttribute("class", "cube-tarot-image cube-connector-card");
|
||||
connectorImg.setAttribute("href", connectorCardUrl);
|
||||
connectorImg.setAttribute("x", String((labelX - cardW / 2).toFixed(2)));
|
||||
connectorImg.setAttribute("y", String((labelY - cardH / 2).toFixed(2)));
|
||||
connectorImg.setAttribute("width", String(cardW));
|
||||
connectorImg.setAttribute("height", String(cardH));
|
||||
connectorImg.setAttribute("role", "button");
|
||||
connectorImg.setAttribute("tabindex", "0");
|
||||
connectorImg.setAttribute("aria-label", `Open ${connectorTarotCard || connector?.name || "connector"} card image`);
|
||||
connectorImg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
||||
connectorImg.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
selectConnector();
|
||||
openTarotCardLightbox(connectorTarotCard, connectorCardUrl, connector?.name || "Mother connector");
|
||||
});
|
||||
connectorImg.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
selectConnector();
|
||||
openTarotCardLightbox(connectorTarotCard, connectorCardUrl, connector?.name || "Mother connector");
|
||||
}
|
||||
});
|
||||
group.appendChild(connectorImg);
|
||||
} else {
|
||||
const connectorText = document.createElementNS(svgNS, "text");
|
||||
@@ -948,12 +952,6 @@
|
||||
group.appendChild(connectorText);
|
||||
}
|
||||
|
||||
const selectConnector = () => {
|
||||
state.selectedNodeType = "connector";
|
||||
state.selectedConnectorId = connectorId;
|
||||
render(getElements());
|
||||
};
|
||||
|
||||
group.addEventListener("click", selectConnector);
|
||||
group.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
@@ -1049,14 +1047,31 @@
|
||||
if (edgeCardUrl) {
|
||||
const cardW = edgeIsActive ? 28 : 20;
|
||||
const cardH = edgeIsActive ? 42 : 30;
|
||||
const edgeTarotCard = getEdgeTarotCard(edge);
|
||||
const cardImg = document.createElementNS(svgNS, "image");
|
||||
cardImg.setAttribute("class", `cube-direction-card${edgeIsActive ? " is-active" : ""}`);
|
||||
cardImg.setAttribute("class", `cube-tarot-image cube-direction-card${edgeIsActive ? " is-active" : ""}`);
|
||||
cardImg.setAttribute("href", edgeCardUrl);
|
||||
cardImg.setAttribute("x", String((labelX - cardW / 2).toFixed(2)));
|
||||
cardImg.setAttribute("y", String((labelY - cardH / 2).toFixed(2)));
|
||||
cardImg.setAttribute("width", String(cardW));
|
||||
cardImg.setAttribute("height", String(cardH));
|
||||
cardImg.setAttribute("role", "button");
|
||||
cardImg.setAttribute("tabindex", "0");
|
||||
cardImg.setAttribute("aria-label", `Open ${edgeTarotCard || edge?.name || "edge"} card image`);
|
||||
cardImg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
||||
cardImg.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
selectEdge();
|
||||
openTarotCardLightbox(edgeTarotCard, edgeCardUrl, edge?.name || "Cube edge");
|
||||
});
|
||||
cardImg.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
selectEdge();
|
||||
openTarotCardLightbox(edgeTarotCard, edgeCardUrl, edge?.name || "Cube edge");
|
||||
}
|
||||
});
|
||||
marker.appendChild(cardImg);
|
||||
} else {
|
||||
const markerText = document.createElementNS(svgNS, "text");
|
||||
@@ -1117,13 +1132,35 @@
|
||||
if (state.markerDisplayMode === "tarot" && centerCardUrl) {
|
||||
const cardW = 24;
|
||||
const cardH = 36;
|
||||
const centerTarotCard = getCenterTarotCard(center);
|
||||
const centerImg = document.createElementNS(svgNS, "image");
|
||||
centerImg.setAttribute("class", "cube-tarot-image cube-center-card");
|
||||
centerImg.setAttribute("href", centerCardUrl);
|
||||
centerImg.setAttribute("x", String((CUBE_VIEW_CENTER.x - cardW / 2).toFixed(2)));
|
||||
centerImg.setAttribute("y", String((CUBE_VIEW_CENTER.y - cardH / 2).toFixed(2)));
|
||||
centerImg.setAttribute("width", String(cardW));
|
||||
centerImg.setAttribute("height", String(cardH));
|
||||
centerImg.setAttribute("role", "button");
|
||||
centerImg.setAttribute("tabindex", "0");
|
||||
centerImg.setAttribute("aria-label", `Open ${centerTarotCard || "Primal Point"} card image`);
|
||||
centerImg.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
||||
centerImg.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
state.selectedNodeType = "center";
|
||||
state.selectedConnectorId = null;
|
||||
render(getElements());
|
||||
openTarotCardLightbox(centerTarotCard, centerCardUrl, "Primal Point");
|
||||
});
|
||||
centerImg.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
state.selectedNodeType = "center";
|
||||
state.selectedConnectorId = null;
|
||||
render(getElements());
|
||||
openTarotCardLightbox(centerTarotCard, centerCardUrl, "Primal Point");
|
||||
}
|
||||
});
|
||||
centerMarker.appendChild(centerImg);
|
||||
} else {
|
||||
const centerText = document.createElementNS(svgNS, "text");
|
||||
@@ -1172,287 +1209,43 @@
|
||||
containerEl.replaceChildren(svg);
|
||||
}
|
||||
|
||||
function renderCenterDetail(elements) {
|
||||
if (!state.showPrimalPoint) {
|
||||
function selectEdgeById(edgeId, preferredWallId = "") {
|
||||
const edge = getEdgeById(edgeId);
|
||||
if (!edge) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const center = getCubeCenterData();
|
||||
if (!center || !elements?.detailNameEl || !elements?.detailSubEl || !elements?.detailBodyEl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const centerLetterId = getCenterLetterId(center);
|
||||
const centerLetter = getCenterLetterSymbol(center);
|
||||
const centerLetterText = centerLetterId
|
||||
? `${centerLetter ? `${centerLetter} ` : ""}${toDisplayText(centerLetterId)}`
|
||||
: "";
|
||||
const centerElement = toDisplayText(center?.element);
|
||||
|
||||
elements.detailNameEl.textContent = "Primal Point";
|
||||
elements.detailSubEl.textContent = [centerLetterText, centerElement].filter(Boolean).join(" · ") || "Center of the Cube";
|
||||
|
||||
const bodyEl = elements.detailBodyEl;
|
||||
bodyEl.innerHTML = "";
|
||||
|
||||
const summary = document.createElement("div");
|
||||
summary.className = "planet-text";
|
||||
summary.innerHTML = `
|
||||
<dl class="alpha-dl">
|
||||
<dt>Name</dt><dd>${toDetailValueMarkup(center?.name)}</dd>
|
||||
<dt>Letter</dt><dd>${toDetailValueMarkup(centerLetterText)}</dd>
|
||||
<dt>Element</dt><dd>${toDetailValueMarkup(center?.element)}</dd>
|
||||
</dl>
|
||||
`;
|
||||
bodyEl.appendChild(createMetaCard("Center Details", summary));
|
||||
|
||||
if (Array.isArray(center?.keywords) && center.keywords.length) {
|
||||
bodyEl.appendChild(createMetaCard("Keywords", center.keywords.join(", ")));
|
||||
}
|
||||
|
||||
if (center?.description) {
|
||||
bodyEl.appendChild(createMetaCard("Description", center.description));
|
||||
}
|
||||
|
||||
const associations = center?.associations || {};
|
||||
const links = document.createElement("div");
|
||||
links.className = "kab-god-links";
|
||||
|
||||
if (centerLetterId) {
|
||||
links.appendChild(createNavButton(centerLetter || "!", "nav:alphabet", {
|
||||
alphabet: "hebrew",
|
||||
hebrewLetterId: centerLetterId
|
||||
}));
|
||||
}
|
||||
|
||||
const centerTrumpNo = toFiniteNumber(associations?.tarotTrumpNumber);
|
||||
const centerTarotCard = toDisplayText(associations?.tarotCard);
|
||||
if (centerTarotCard || centerTrumpNo != null) {
|
||||
links.appendChild(createNavButton(centerTarotCard || `Trump ${centerTrumpNo}`, "nav:tarot-trump", {
|
||||
cardName: centerTarotCard,
|
||||
trumpNumber: centerTrumpNo
|
||||
}));
|
||||
}
|
||||
|
||||
const centerPathNo = toFiniteNumber(associations?.kabbalahPathNumber);
|
||||
if (centerPathNo != null) {
|
||||
links.appendChild(createNavButton(`Path ${centerPathNo}`, "nav:kabbalah-path", {
|
||||
pathNo: centerPathNo
|
||||
}));
|
||||
}
|
||||
|
||||
if (links.childElementCount) {
|
||||
const linksCard = document.createElement("div");
|
||||
linksCard.className = "planet-meta-card";
|
||||
linksCard.innerHTML = "<strong>Correspondence Links</strong>";
|
||||
linksCard.appendChild(links);
|
||||
bodyEl.appendChild(linksCard);
|
||||
const currentWallId = normalizeId(state.selectedWallId);
|
||||
const preferredId = normalizeId(preferredWallId);
|
||||
const edgeWalls = getEdgeWalls(edge);
|
||||
const nextWallId = preferredId && edgeWalls.includes(preferredId)
|
||||
? preferredId
|
||||
: (edgeWalls.includes(currentWallId) ? currentWallId : (edgeWalls[0] || currentWallId));
|
||||
|
||||
state.selectedEdgeId = normalizeEdgeId(edge.id);
|
||||
state.selectedNodeType = "wall";
|
||||
state.selectedConnectorId = null;
|
||||
|
||||
if (nextWallId) {
|
||||
if (nextWallId !== currentWallId) {
|
||||
state.selectedWallId = nextWallId;
|
||||
snapRotationToWall(nextWallId);
|
||||
} else if (!state.selectedWallId) {
|
||||
state.selectedWallId = nextWallId;
|
||||
}
|
||||
}
|
||||
|
||||
render(getElements());
|
||||
return true;
|
||||
}
|
||||
|
||||
function renderConnectorDetail(elements, walls) {
|
||||
const connector = getConnectorById(state.selectedConnectorId);
|
||||
if (!connector || !elements?.detailNameEl || !elements?.detailSubEl || !elements?.detailBodyEl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fromWallId = normalizeId(connector?.fromWallId);
|
||||
const toWallId = normalizeId(connector?.toWallId);
|
||||
const fromWall = getWallById(fromWallId) || walls.find((entry) => normalizeId(entry?.id) === fromWallId) || null;
|
||||
const toWall = getWallById(toWallId) || walls.find((entry) => normalizeId(entry?.id) === toWallId) || null;
|
||||
const connectorPath = getConnectorPathEntry(connector);
|
||||
|
||||
const letterId = normalizeLetterKey(connector?.hebrewLetterId);
|
||||
const letterSymbol = getHebrewLetterSymbol(letterId);
|
||||
const letterText = letterId
|
||||
? `${letterSymbol ? `${letterSymbol} ` : ""}${toDisplayText(letterId)}`
|
||||
: "";
|
||||
|
||||
const pathNo = toFiniteNumber(connectorPath?.pathNumber);
|
||||
const tarotCard = toDisplayText(connectorPath?.tarot?.card);
|
||||
const tarotTrumpNumber = toFiniteNumber(connectorPath?.tarot?.trumpNumber);
|
||||
const astrologyType = toDisplayText(connectorPath?.astrology?.type);
|
||||
const astrologyName = toDisplayText(connectorPath?.astrology?.name);
|
||||
const astrologySummary = [astrologyType, astrologyName].filter(Boolean).join(": ");
|
||||
|
||||
elements.detailNameEl.textContent = connector?.name || "Mother Connector";
|
||||
elements.detailSubEl.textContent = ["Mother Letter", letterText].filter(Boolean).join(" · ") || "Mother Letter";
|
||||
|
||||
const bodyEl = elements.detailBodyEl;
|
||||
bodyEl.innerHTML = "";
|
||||
|
||||
const summary = document.createElement("div");
|
||||
summary.className = "planet-text";
|
||||
summary.innerHTML = `
|
||||
<dl class="alpha-dl">
|
||||
<dt>Letter</dt><dd>${toDetailValueMarkup(letterText)}</dd>
|
||||
<dt>From</dt><dd>${toDetailValueMarkup(fromWall?.name || formatDirectionName(fromWallId))}</dd>
|
||||
<dt>To</dt><dd>${toDetailValueMarkup(toWall?.name || formatDirectionName(toWallId))}</dd>
|
||||
<dt>Tarot</dt><dd>${toDetailValueMarkup(tarotCard || (tarotTrumpNumber != null ? `Trump ${tarotTrumpNumber}` : ""))}</dd>
|
||||
</dl>
|
||||
`;
|
||||
bodyEl.appendChild(createMetaCard("Connector Details", summary));
|
||||
|
||||
if (astrologySummary) {
|
||||
bodyEl.appendChild(createMetaCard("Astrology", astrologySummary));
|
||||
}
|
||||
|
||||
const links = document.createElement("div");
|
||||
links.className = "kab-god-links";
|
||||
|
||||
if (letterId) {
|
||||
links.appendChild(createNavButton(letterSymbol || "!", "nav:alphabet", {
|
||||
alphabet: "hebrew",
|
||||
hebrewLetterId: letterId
|
||||
}));
|
||||
}
|
||||
|
||||
if (pathNo != null) {
|
||||
links.appendChild(createNavButton(`Path ${pathNo}`, "nav:kabbalah-path", {
|
||||
pathNo
|
||||
}));
|
||||
}
|
||||
|
||||
if (tarotCard || tarotTrumpNumber != null) {
|
||||
links.appendChild(createNavButton(tarotCard || `Trump ${tarotTrumpNumber}`, "nav:tarot-trump", {
|
||||
cardName: tarotCard,
|
||||
trumpNumber: tarotTrumpNumber
|
||||
}));
|
||||
}
|
||||
|
||||
if (links.childElementCount) {
|
||||
const linksCard = document.createElement("div");
|
||||
linksCard.className = "planet-meta-card";
|
||||
linksCard.innerHTML = "<strong>Correspondence Links</strong>";
|
||||
linksCard.appendChild(links);
|
||||
bodyEl.appendChild(linksCard);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function renderEdgeCard(wall, detailBodyEl, wallEdgeDirections = new Map()) {
|
||||
const wallId = normalizeId(wall?.id);
|
||||
const selectedEdge = getEdgeById(state.selectedEdgeId)
|
||||
|| getEdgesForWall(wallId)[0]
|
||||
|| getEdges()[0]
|
||||
|| null;
|
||||
if (!selectedEdge) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.selectedEdgeId = normalizeEdgeId(selectedEdge.id);
|
||||
|
||||
const edgeDirection = wallEdgeDirections.get(normalizeEdgeId(selectedEdge.id));
|
||||
const edgeName = edgeDirection
|
||||
? formatDirectionName(edgeDirection)
|
||||
: (toDisplayText(selectedEdge.name) || formatEdgeName(selectedEdge.id));
|
||||
const edgeWalls = getEdgeWalls(selectedEdge)
|
||||
.map((entry) => entry.charAt(0).toUpperCase() + entry.slice(1))
|
||||
.join(" · ");
|
||||
|
||||
const edgeLetterId = getEdgeLetterId(selectedEdge);
|
||||
const edgeLetter = getEdgeLetter(selectedEdge);
|
||||
const edgePath = getEdgePathEntry(selectedEdge);
|
||||
const astrologyType = toDisplayText(edgePath?.astrology?.type);
|
||||
const astrologyName = toDisplayText(edgePath?.astrology?.name);
|
||||
const astrologySymbol = getEdgeAstrologySymbol(selectedEdge);
|
||||
const astrologyText = astrologySymbol && astrologyName
|
||||
? `${astrologySymbol} ${astrologyName}`
|
||||
: astrologySymbol || astrologyName;
|
||||
|
||||
const pathNo = toFiniteNumber(edgePath?.pathNumber);
|
||||
const tarotCard = toDisplayText(edgePath?.tarot?.card);
|
||||
const tarotTrumpNumber = toFiniteNumber(edgePath?.tarot?.trumpNumber);
|
||||
|
||||
const edgeCard = document.createElement("div");
|
||||
edgeCard.className = "planet-meta-card";
|
||||
|
||||
const title = document.createElement("strong");
|
||||
title.textContent = `Edge · ${edgeName}`;
|
||||
edgeCard.appendChild(title);
|
||||
|
||||
const dlWrap = document.createElement("div");
|
||||
dlWrap.className = "planet-text";
|
||||
dlWrap.innerHTML = `
|
||||
<dl class="alpha-dl">
|
||||
<dt>Direction</dt><dd>${toDetailValueMarkup(edgeName)}</dd>
|
||||
<dt>Edge</dt><dd>${toDetailValueMarkup(edgeWalls)}</dd>
|
||||
<dt>Letter</dt><dd>${toDetailValueMarkup(edgeLetter)}</dd>
|
||||
<dt>Astrology</dt><dd>${toDetailValueMarkup(astrologyText)}</dd>
|
||||
<dt>Tarot</dt><dd>${toDetailValueMarkup(tarotCard)}</dd>
|
||||
</dl>
|
||||
`;
|
||||
edgeCard.appendChild(dlWrap);
|
||||
|
||||
if (Array.isArray(selectedEdge.keywords) && selectedEdge.keywords.length) {
|
||||
const keywords = document.createElement("p");
|
||||
keywords.className = "planet-text";
|
||||
keywords.textContent = selectedEdge.keywords.join(", ");
|
||||
edgeCard.appendChild(keywords);
|
||||
}
|
||||
|
||||
if (selectedEdge.description) {
|
||||
const description = document.createElement("p");
|
||||
description.className = "planet-text";
|
||||
description.textContent = selectedEdge.description;
|
||||
edgeCard.appendChild(description);
|
||||
}
|
||||
|
||||
const links = document.createElement("div");
|
||||
links.className = "kab-god-links";
|
||||
|
||||
if (edgeLetterId) {
|
||||
links.appendChild(createNavButton(edgeLetter || "!", "nav:alphabet", {
|
||||
alphabet: "hebrew",
|
||||
hebrewLetterId: edgeLetterId
|
||||
}));
|
||||
}
|
||||
|
||||
if (astrologyType === "zodiac" && astrologyName) {
|
||||
links.appendChild(createNavButton(astrologyName, "nav:zodiac", {
|
||||
signId: normalizeId(astrologyName)
|
||||
}));
|
||||
}
|
||||
|
||||
if (tarotCard) {
|
||||
links.appendChild(createNavButton(tarotCard, "nav:tarot-trump", {
|
||||
cardName: tarotCard,
|
||||
trumpNumber: tarotTrumpNumber
|
||||
}));
|
||||
}
|
||||
|
||||
if (pathNo != null) {
|
||||
links.appendChild(createNavButton(`Path ${pathNo}`, "nav:kabbalah-path", {
|
||||
pathNo
|
||||
}));
|
||||
}
|
||||
|
||||
if (links.childElementCount) {
|
||||
edgeCard.appendChild(links);
|
||||
}
|
||||
|
||||
detailBodyEl.appendChild(edgeCard);
|
||||
}
|
||||
|
||||
function renderDetail(elements, walls) {
|
||||
if (state.selectedNodeType === "connector" && renderConnectorDetail(elements, walls)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.selectedNodeType === "center" && renderCenterDetail(elements)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const wall = getWallById(state.selectedWallId) || walls[0] || null;
|
||||
if (!wall || !elements?.detailNameEl || !elements?.detailSubEl || !elements?.detailBodyEl) {
|
||||
if (typeof cubeDetailUi.renderDetail !== "function") {
|
||||
if (elements?.detailNameEl) {
|
||||
elements.detailNameEl.textContent = "Cube data unavailable";
|
||||
}
|
||||
if (elements?.detailSubEl) {
|
||||
elements.detailSubEl.textContent = "Could not load cube dataset.";
|
||||
elements.detailSubEl.textContent = "Cube detail renderer missing.";
|
||||
}
|
||||
if (elements?.detailBodyEl) {
|
||||
elements.detailBodyEl.innerHTML = "";
|
||||
@@ -1460,152 +1253,40 @@
|
||||
return;
|
||||
}
|
||||
|
||||
state.selectedWallId = normalizeId(wall.id);
|
||||
|
||||
const wallPlanet = toDisplayText(wall?.planet) || "!";
|
||||
const wallElement = toDisplayText(wall?.element) || "!";
|
||||
const wallFaceLetterId = getWallFaceLetterId(wall);
|
||||
const wallFaceLetter = getWallFaceLetter(wall);
|
||||
const wallFaceLetterText = wallFaceLetterId
|
||||
? `${wallFaceLetter ? `${wallFaceLetter} ` : ""}${toDisplayText(wallFaceLetterId)}`
|
||||
: "";
|
||||
elements.detailNameEl.textContent = `${wall.name} Wall`;
|
||||
elements.detailSubEl.textContent = `${wallElement} · ${wallPlanet}`;
|
||||
|
||||
const bodyEl = elements.detailBodyEl;
|
||||
bodyEl.innerHTML = "";
|
||||
|
||||
const summary = document.createElement("div");
|
||||
summary.className = "planet-text";
|
||||
summary.innerHTML = `
|
||||
<dl class="alpha-dl">
|
||||
<dt>Opposite</dt><dd>${toDetailValueMarkup(wall.opposite)}</dd>
|
||||
<dt>Face Letter</dt><dd>${toDetailValueMarkup(wallFaceLetterText)}</dd>
|
||||
<dt>Element</dt><dd>${toDetailValueMarkup(wall.element)}</dd>
|
||||
<dt>Planet</dt><dd>${toDetailValueMarkup(wall.planet)}</dd>
|
||||
<dt>Archangel</dt><dd>${toDetailValueMarkup(wall.archangel)}</dd>
|
||||
</dl>
|
||||
`;
|
||||
bodyEl.appendChild(createMetaCard("Wall Details", summary));
|
||||
|
||||
if (Array.isArray(wall.keywords) && wall.keywords.length) {
|
||||
bodyEl.appendChild(createMetaCard("Keywords", wall.keywords.join(", ")));
|
||||
}
|
||||
|
||||
if (wall.description) {
|
||||
bodyEl.appendChild(createMetaCard("Description", wall.description));
|
||||
}
|
||||
|
||||
const wallLinksCard = document.createElement("div");
|
||||
wallLinksCard.className = "planet-meta-card";
|
||||
wallLinksCard.innerHTML = "<strong>Correspondence Links</strong>";
|
||||
const wallLinks = document.createElement("div");
|
||||
wallLinks.className = "kab-god-links";
|
||||
|
||||
if (wallFaceLetterId) {
|
||||
const wallFaceLetterName = getHebrewLetterName(wallFaceLetterId) || toDisplayText(wallFaceLetterId);
|
||||
const faceLetterText = [wallFaceLetter, wallFaceLetterName].filter(Boolean).join(" ");
|
||||
const faceLetterLabel = faceLetterText
|
||||
? `Face ${faceLetterText}`
|
||||
: "Face !";
|
||||
wallLinks.appendChild(createNavButton(faceLetterLabel, "nav:alphabet", {
|
||||
alphabet: "hebrew",
|
||||
hebrewLetterId: wallFaceLetterId
|
||||
}));
|
||||
}
|
||||
|
||||
const wallAssociations = wall.associations || {};
|
||||
if (wallAssociations.planetId) {
|
||||
wallLinks.appendChild(createNavButton(toDisplayText(wall.planet) || "!", "nav:planet", {
|
||||
planetId: wallAssociations.planetId
|
||||
}));
|
||||
}
|
||||
|
||||
if (wallAssociations.godName) {
|
||||
wallLinks.appendChild(createNavButton(wallAssociations.godName, "nav:gods", {
|
||||
godName: wallAssociations.godName
|
||||
}));
|
||||
}
|
||||
|
||||
if (wall.oppositeWallId) {
|
||||
const oppositeWall = getWallById(wall.oppositeWallId);
|
||||
const internal = document.createElement("button");
|
||||
internal.type = "button";
|
||||
internal.className = "kab-god-link";
|
||||
internal.textContent = `Opposite: ${oppositeWall?.name || wall.oppositeWallId}`;
|
||||
internal.addEventListener("click", () => {
|
||||
state.selectedWallId = normalizeId(wall.oppositeWallId);
|
||||
state.selectedEdgeId = normalizeEdgeId(getEdgesForWall(state.selectedWallId)[0]?.id || getEdges()[0]?.id);
|
||||
state.selectedNodeType = "wall";
|
||||
state.selectedConnectorId = null;
|
||||
snapRotationToWall(state.selectedWallId);
|
||||
render(getElements());
|
||||
});
|
||||
wallLinks.appendChild(internal);
|
||||
}
|
||||
|
||||
if (wallLinks.childElementCount) {
|
||||
wallLinksCard.appendChild(wallLinks);
|
||||
bodyEl.appendChild(wallLinksCard);
|
||||
}
|
||||
|
||||
const edgesCard = document.createElement("div");
|
||||
edgesCard.className = "planet-meta-card";
|
||||
edgesCard.innerHTML = "<strong>Wall Edges</strong>";
|
||||
|
||||
const chips = document.createElement("div");
|
||||
chips.className = "kab-chips";
|
||||
|
||||
const wallEdgeDirections = getWallEdgeDirections(wall);
|
||||
const wallEdges = getEdgesForWall(wall)
|
||||
.slice()
|
||||
.sort((left, right) => {
|
||||
const leftDirection = wallEdgeDirections.get(normalizeEdgeId(left?.id));
|
||||
const rightDirection = wallEdgeDirections.get(normalizeEdgeId(right?.id));
|
||||
const leftRank = LOCAL_DIRECTION_RANK[leftDirection] ?? LOCAL_DIRECTION_ORDER.length;
|
||||
const rightRank = LOCAL_DIRECTION_RANK[rightDirection] ?? LOCAL_DIRECTION_ORDER.length;
|
||||
if (leftRank !== rightRank) {
|
||||
return leftRank - rightRank;
|
||||
}
|
||||
return normalizeEdgeId(left?.id).localeCompare(normalizeEdgeId(right?.id));
|
||||
});
|
||||
|
||||
wallEdges.forEach((edge) => {
|
||||
const id = normalizeEdgeId(edge.id);
|
||||
const chipLetter = getEdgeLetter(edge);
|
||||
const chipIsMissing = !chipLetter;
|
||||
const direction = wallEdgeDirections.get(id);
|
||||
const directionLabel = direction
|
||||
? formatDirectionName(direction)
|
||||
: (toDisplayText(edge.name) || formatEdgeName(edge.id));
|
||||
const chip = document.createElement("span");
|
||||
chip.className = `kab-chip${id === normalizeEdgeId(state.selectedEdgeId) ? " is-active" : ""}${chipIsMissing ? " is-missing" : ""}`;
|
||||
chip.setAttribute("role", "button");
|
||||
chip.setAttribute("tabindex", "0");
|
||||
chip.textContent = `${directionLabel} · ${chipLetter || "!"}`;
|
||||
|
||||
const selectEdge = () => {
|
||||
state.selectedEdgeId = id;
|
||||
state.selectedNodeType = "wall";
|
||||
state.selectedConnectorId = null;
|
||||
render(getElements());
|
||||
};
|
||||
|
||||
chip.addEventListener("click", selectEdge);
|
||||
chip.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
selectEdge();
|
||||
}
|
||||
});
|
||||
|
||||
chips.appendChild(chip);
|
||||
cubeDetailUi.renderDetail({
|
||||
state,
|
||||
elements,
|
||||
walls,
|
||||
normalizeId,
|
||||
normalizeEdgeId,
|
||||
normalizeLetterKey,
|
||||
formatDirectionName,
|
||||
formatEdgeName,
|
||||
toFiniteNumber,
|
||||
getWallById,
|
||||
getEdgeById,
|
||||
getEdges,
|
||||
getEdgeWalls,
|
||||
getEdgesForWall,
|
||||
getWallEdgeDirections,
|
||||
getConnectorById,
|
||||
getConnectorPathEntry,
|
||||
getCubeCenterData,
|
||||
getCenterLetterId,
|
||||
getCenterLetterSymbol,
|
||||
getEdgeLetterId,
|
||||
getEdgeLetter,
|
||||
getEdgePathEntry,
|
||||
getEdgeAstrologySymbol,
|
||||
getWallFaceLetterId,
|
||||
getWallFaceLetter,
|
||||
getHebrewLetterName,
|
||||
getHebrewLetterSymbol,
|
||||
localDirectionOrder: LOCAL_DIRECTION_ORDER,
|
||||
localDirectionRank: LOCAL_DIRECTION_RANK,
|
||||
onSelectWall: selectWallById,
|
||||
onSelectEdge: selectEdgeById
|
||||
});
|
||||
|
||||
edgesCard.appendChild(chips);
|
||||
bodyEl.appendChild(edgesCard);
|
||||
|
||||
renderEdgeCard(wall, bodyEl, wallEdgeDirections);
|
||||
}
|
||||
|
||||
function render(elements) {
|
||||
|
||||
Reference in New Issue
Block a user