update
This commit is contained in:
@@ -100,9 +100,16 @@
|
|||||||
state,
|
state,
|
||||||
normalizeId,
|
normalizeId,
|
||||||
getDomRefs,
|
getDomRefs,
|
||||||
renderDetail
|
renderDetail,
|
||||||
|
onStateChange
|
||||||
} = dependencies || {};
|
} = dependencies || {};
|
||||||
|
|
||||||
|
function notifyStateChange() {
|
||||||
|
if (typeof onStateChange === "function") {
|
||||||
|
onStateChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function capitalize(value) {
|
function capitalize(value) {
|
||||||
return value ? value.charAt(0).toUpperCase() + value.slice(1) : "";
|
return value ? value.charAt(0).toUpperCase() + value.slice(1) : "";
|
||||||
}
|
}
|
||||||
@@ -405,6 +412,7 @@
|
|||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
renderDetail(selected);
|
renderDetail(selected);
|
||||||
|
notifyStateChange();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,6 +421,7 @@
|
|||||||
if (detailSubEl) {
|
if (detailSubEl) {
|
||||||
detailSubEl.textContent = "No letters match the current filter.";
|
detailSubEl.textContent = "No letters match the current filter.";
|
||||||
}
|
}
|
||||||
|
notifyStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindFilterControls() {
|
function bindFilterControls() {
|
||||||
@@ -530,6 +539,7 @@
|
|||||||
}
|
}
|
||||||
if (detailSubEl) detailSubEl.textContent = "Select a letter to explore";
|
if (detailSubEl) detailSubEl.textContent = "Select a letter to explore";
|
||||||
if (detailBodyEl) detailBodyEl.innerHTML = "";
|
if (detailBodyEl) detailBodyEl.innerHTML = "";
|
||||||
|
notifyStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectLetter(key) {
|
function selectLetter(key) {
|
||||||
@@ -539,6 +549,8 @@
|
|||||||
const letter = letters.find((entry) => letterKey(entry) === key) || getLetters().find((entry) => letterKey(entry) === key);
|
const letter = letters.find((entry) => letterKey(entry) === key) || getLetters().find((entry) => letterKey(entry) === key);
|
||||||
if (letter) {
|
if (letter) {
|
||||||
renderDetail(letter);
|
renderDetail(letter);
|
||||||
|
} else {
|
||||||
|
notifyStateChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,10 +573,14 @@
|
|||||||
const letter = letters.find((entry) => letterKey(entry) === selectKey) || getLetters().find((entry) => letterKey(entry) === selectKey);
|
const letter = letters.find((entry) => letterKey(entry) === selectKey) || getLetters().find((entry) => letterKey(entry) === selectKey);
|
||||||
if (letter) {
|
if (letter) {
|
||||||
renderDetail(letter);
|
renderDetail(letter);
|
||||||
|
} else {
|
||||||
|
notifyStateChange();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resetDetail();
|
resetDetail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notifyStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+104
-1
@@ -42,13 +42,16 @@
|
|||||||
},
|
},
|
||||||
gematriaDb: null
|
gematriaDb: null
|
||||||
};
|
};
|
||||||
|
let detailNavigator = null;
|
||||||
|
|
||||||
function arabicDisplayName(letter) {
|
function arabicDisplayName(letter) {
|
||||||
return browserUi.arabicDisplayName(letter);
|
return browserUi.arabicDisplayName(letter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Element cache ────────────────────────────────────────────────────
|
// ── Element cache ────────────────────────────────────────────────────
|
||||||
|
let alphabetLettersSectionEl;
|
||||||
let listEl, countEl, detailNameEl, detailSubEl, detailBodyEl;
|
let listEl, countEl, detailNameEl, detailSubEl, detailBodyEl;
|
||||||
|
let detailPrevEl, detailPositionEl, detailNextEl;
|
||||||
let tabAll, tabHebrew, tabGreek, tabGreekArchaic, tabEnglish, tabArabic, tabEnochian;
|
let tabAll, tabHebrew, tabGreek, tabGreekArchaic, tabEnglish, tabArabic, tabEnochian;
|
||||||
let searchInputEl, searchClearEl, typeFilterEl;
|
let searchInputEl, searchClearEl, typeFilterEl;
|
||||||
let gematriaCipherEl, gematriaInputEl, gematriaResultEl, gematriaBreakdownEl;
|
let gematriaCipherEl, gematriaInputEl, gematriaResultEl, gematriaBreakdownEl;
|
||||||
@@ -56,11 +59,15 @@
|
|||||||
let gematriaReverseCiphersEl, gematriaReverseCipherHintEl;
|
let gematriaReverseCiphersEl, gematriaReverseCipherHintEl;
|
||||||
|
|
||||||
function getElements() {
|
function getElements() {
|
||||||
|
alphabetLettersSectionEl = document.getElementById("alphabet-letters-section");
|
||||||
listEl = document.getElementById("alpha-letter-list");
|
listEl = document.getElementById("alpha-letter-list");
|
||||||
countEl = document.getElementById("alpha-letter-count");
|
countEl = document.getElementById("alpha-letter-count");
|
||||||
detailNameEl = document.getElementById("alpha-detail-name");
|
detailNameEl = document.getElementById("alpha-detail-name");
|
||||||
detailSubEl = document.getElementById("alpha-detail-sub");
|
detailSubEl = document.getElementById("alpha-detail-sub");
|
||||||
detailBodyEl = document.getElementById("alpha-detail-body");
|
detailBodyEl = document.getElementById("alpha-detail-body");
|
||||||
|
detailPrevEl = document.getElementById("alpha-detail-prev");
|
||||||
|
detailPositionEl = document.getElementById("alpha-detail-position");
|
||||||
|
detailNextEl = document.getElementById("alpha-detail-next");
|
||||||
tabAll = document.getElementById("alpha-tab-all");
|
tabAll = document.getElementById("alpha-tab-all");
|
||||||
tabHebrew = document.getElementById("alpha-tab-hebrew");
|
tabHebrew = document.getElementById("alpha-tab-hebrew");
|
||||||
tabGreek = document.getElementById("alpha-tab-greek");
|
tabGreek = document.getElementById("alpha-tab-greek");
|
||||||
@@ -218,6 +225,99 @@
|
|||||||
if (typeof alphabetDetailUi.renderDetail === "function") {
|
if (typeof alphabetDetailUi.renderDetail === "function") {
|
||||||
alphabetDetailUi.renderDetail(getDetailRenderContext(letter, alphabet));
|
alphabetDetailUi.renderDetail(getDetailRenderContext(letter, alphabet));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syncDetailNavigation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLetterSequenceState() {
|
||||||
|
const filteredLetters = getFilteredLetters();
|
||||||
|
const selectedLetter = filteredLetters.find((letter) => letterKey(letter) === state.selectedKey)
|
||||||
|
|| getLetters().find((letter) => letterKey(letter) === state.selectedKey)
|
||||||
|
|| null;
|
||||||
|
|
||||||
|
const selectedAlphabet = state.activeAlphabet === "all"
|
||||||
|
? String(alphabetForLetter(selectedLetter) || "").trim().toLowerCase()
|
||||||
|
: state.activeAlphabet;
|
||||||
|
|
||||||
|
const letters = state.activeAlphabet === "all" && selectedAlphabet
|
||||||
|
? filteredLetters.filter((letter) => alphabetForLetter(letter) === selectedAlphabet)
|
||||||
|
: filteredLetters;
|
||||||
|
|
||||||
|
const total = letters.length;
|
||||||
|
const currentIndex = letters.findIndex((letter) => letterKey(letter) === state.selectedKey);
|
||||||
|
|
||||||
|
return {
|
||||||
|
total,
|
||||||
|
currentIndex,
|
||||||
|
previousKey: currentIndex > 0 ? letterKey(letters[currentIndex - 1]) : "",
|
||||||
|
nextKey: currentIndex >= 0 && currentIndex < total - 1 ? letterKey(letters[currentIndex + 1]) : ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollLetterIntoView(keyToReveal, elements) {
|
||||||
|
if (!elements?.listEl || !keyToReveal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = Array.from(elements.listEl.querySelectorAll(".alpha-list-item"))
|
||||||
|
.find((entry) => entry.dataset.key === keyToReveal);
|
||||||
|
|
||||||
|
match?.scrollIntoView({ block: "nearest" });
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDetailNavigator() {
|
||||||
|
if (detailNavigator || typeof window.TarotSequenceNav?.createSequenceNavigator !== "function") {
|
||||||
|
return detailNavigator;
|
||||||
|
}
|
||||||
|
|
||||||
|
detailNavigator = window.TarotSequenceNav.createSequenceNavigator({
|
||||||
|
getElements: () => ({
|
||||||
|
alphabetLettersSectionEl,
|
||||||
|
listEl,
|
||||||
|
detailPrevEl,
|
||||||
|
detailPositionEl,
|
||||||
|
detailNextEl
|
||||||
|
}),
|
||||||
|
isActive: (elements) => Boolean(elements?.alphabetLettersSectionEl && elements.alphabetLettersSectionEl.hidden === false),
|
||||||
|
getSequenceState: getLetterSequenceState,
|
||||||
|
getPrevButton: (elements) => elements?.detailPrevEl,
|
||||||
|
getNextButton: (elements) => elements?.detailNextEl,
|
||||||
|
getPositionEl: (elements) => elements?.detailPositionEl,
|
||||||
|
formatPositionText: ({ total, currentIndex }) => {
|
||||||
|
const sequenceState = getLetterSequenceState();
|
||||||
|
const alphabetLabel = sequenceState.selectedAlphabet
|
||||||
|
? `${sequenceState.selectedAlphabet} `
|
||||||
|
: "";
|
||||||
|
|
||||||
|
if (total > 0 && currentIndex >= 0) {
|
||||||
|
const suffix = (state.activeAlphabet !== "all" || String(state.filters.query || "").trim() || state.filters.letterType)
|
||||||
|
? " shown"
|
||||||
|
: "";
|
||||||
|
return `${currentIndex + 1} of ${total} ${alphabetLabel}letters${suffix}`.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return total > 0
|
||||||
|
? `${total} ${alphabetLabel}letters`.trim()
|
||||||
|
: "No letters";
|
||||||
|
},
|
||||||
|
selectTarget: (targetKey) => {
|
||||||
|
selectLetter(targetKey);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
afterSelect: (targetKey, elements) => {
|
||||||
|
scrollLetterIntoView(targetKey, elements);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return detailNavigator;
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncDetailNavigation() {
|
||||||
|
getDetailNavigator()?.sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindDetailNavigation() {
|
||||||
|
getDetailNavigator()?.bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
function card(title, bodyHTML) {
|
function card(title, bodyHTML) {
|
||||||
@@ -365,7 +465,8 @@
|
|||||||
searchClearEl,
|
searchClearEl,
|
||||||
typeFilterEl
|
typeFilterEl
|
||||||
}),
|
}),
|
||||||
renderDetail
|
renderDetail,
|
||||||
|
onStateChange: syncDetailNavigation
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── Event delegation on detail body ──────────────────────────────────
|
// ── Event delegation on detail body ──────────────────────────────────
|
||||||
@@ -458,6 +559,7 @@
|
|||||||
// alphabets.json is a top-level file → grouped["alphabets"] = the data object
|
// alphabets.json is a top-level file → grouped["alphabets"] = the data object
|
||||||
|
|
||||||
getElements();
|
getElements();
|
||||||
|
bindDetailNavigation();
|
||||||
ensureGematriaCalculator();
|
ensureGematriaCalculator();
|
||||||
bindFilterControls();
|
bindFilterControls();
|
||||||
syncFilterControls();
|
syncFilterControls();
|
||||||
@@ -476,6 +578,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
switchAlphabet("all", null);
|
switchAlphabet("all", null);
|
||||||
|
syncDetailNavigation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Incoming navigation ───────────────────────────────────────────────
|
// ── Incoming navigation ───────────────────────────────────────────────
|
||||||
|
|||||||
+259
-1
@@ -26,6 +26,261 @@
|
|||||||
return Boolean(document.querySelector("[role='dialog'][aria-modal='true'][aria-hidden='false']"));
|
return Boolean(document.querySelector("[role='dialog'][aria-modal='true'][aria-hidden='false']"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isHiddenElement(element) {
|
||||||
|
if (!(element instanceof HTMLElement)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.hidden || element.getAttribute("aria-hidden") === "true") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAutoSequenceOptions(listEl) {
|
||||||
|
if (!(listEl instanceof HTMLElement)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(listEl.querySelectorAll("[role='option']"))
|
||||||
|
.filter((option) => option instanceof HTMLElement)
|
||||||
|
.filter((option) => !isHiddenElement(option));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAutoSelectedIndex(options) {
|
||||||
|
const selectedIndex = options.findIndex((option) => {
|
||||||
|
if (!(option instanceof HTMLElement)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return option.getAttribute("aria-selected") === "true"
|
||||||
|
|| option.classList.contains("is-selected");
|
||||||
|
});
|
||||||
|
|
||||||
|
return selectedIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAutomaticSequenceControls(sectionEl, headingEl) {
|
||||||
|
if (!(headingEl instanceof HTMLElement)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headingEl.querySelector(".detail-sequence-nav")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const titleText = String(headingEl.querySelector("h2")?.textContent || "items").trim() || "items";
|
||||||
|
const normalizedTitle = titleText
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9]+/g, "-")
|
||||||
|
.replace(/(^-|-$)/g, "");
|
||||||
|
|
||||||
|
const sectionId = String(sectionEl?.id || "section").trim() || "section";
|
||||||
|
const navPrefix = `${sectionId}-${normalizedTitle || "items"}`;
|
||||||
|
|
||||||
|
const navEl = document.createElement("div");
|
||||||
|
navEl.className = "detail-sequence-nav";
|
||||||
|
navEl.dataset.autoSequenceNav = "true";
|
||||||
|
navEl.setAttribute("aria-label", `Browse ${titleText}`);
|
||||||
|
|
||||||
|
const prevButton = document.createElement("button");
|
||||||
|
prevButton.type = "button";
|
||||||
|
prevButton.id = `${navPrefix}-detail-prev-auto`;
|
||||||
|
prevButton.className = "detail-sequence-btn";
|
||||||
|
prevButton.textContent = "Back";
|
||||||
|
prevButton.setAttribute("aria-label", `Previous ${titleText}`);
|
||||||
|
|
||||||
|
const positionEl = document.createElement("div");
|
||||||
|
positionEl.id = `${navPrefix}-detail-position-auto`;
|
||||||
|
positionEl.className = "detail-sequence-position";
|
||||||
|
positionEl.setAttribute("aria-live", "polite");
|
||||||
|
positionEl.textContent = "--";
|
||||||
|
|
||||||
|
const nextButton = document.createElement("button");
|
||||||
|
nextButton.type = "button";
|
||||||
|
nextButton.id = `${navPrefix}-detail-next-auto`;
|
||||||
|
nextButton.className = "detail-sequence-btn";
|
||||||
|
nextButton.textContent = "Next";
|
||||||
|
nextButton.setAttribute("aria-label", `Next ${titleText}`);
|
||||||
|
|
||||||
|
navEl.append(prevButton, positionEl, nextButton);
|
||||||
|
|
||||||
|
const summaryEl = headingEl.querySelector(".planet-detail-summary");
|
||||||
|
if (summaryEl && summaryEl.parentElement === headingEl) {
|
||||||
|
headingEl.insertBefore(navEl, summaryEl);
|
||||||
|
} else {
|
||||||
|
headingEl.appendChild(navEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
sectionEl,
|
||||||
|
listEl: sectionEl.querySelector(".planet-list-panel [role='listbox']"),
|
||||||
|
prevButton,
|
||||||
|
nextButton,
|
||||||
|
positionEl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const automaticNavigators = new WeakMap();
|
||||||
|
let autoScanObserver = null;
|
||||||
|
let autoScanQueued = false;
|
||||||
|
let autoNavigationEnabled = false;
|
||||||
|
|
||||||
|
function createAutomaticNavigatorForSection(sectionEl) {
|
||||||
|
if (!(sectionEl instanceof HTMLElement) || automaticNavigators.has(sectionEl)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const listEl = sectionEl.querySelector(".planet-list-panel [role='listbox']");
|
||||||
|
const headingEl = sectionEl.querySelector(".planet-detail-panel .planet-detail-heading");
|
||||||
|
if (!(listEl instanceof HTMLElement) || !(headingEl instanceof HTMLElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headingEl.querySelector(".detail-sequence-nav")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const controls = createAutomaticSequenceControls(sectionEl, headingEl);
|
||||||
|
if (!controls || !(controls.listEl instanceof HTMLElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navigator = createSequenceNavigator({
|
||||||
|
getElements: () => controls,
|
||||||
|
isActive: (elements) => Boolean(elements?.sectionEl && elements.sectionEl.hidden === false),
|
||||||
|
getSequenceState: () => {
|
||||||
|
const options = getAutoSequenceOptions(controls.listEl);
|
||||||
|
const total = options.length;
|
||||||
|
const currentIndex = getAutoSelectedIndex(options);
|
||||||
|
|
||||||
|
if (!total) {
|
||||||
|
return {
|
||||||
|
total: 0,
|
||||||
|
currentIndex: -1,
|
||||||
|
previousKey: "",
|
||||||
|
nextKey: ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
total,
|
||||||
|
currentIndex,
|
||||||
|
previousKey: currentIndex > 0 ? String(currentIndex - 1) : "",
|
||||||
|
nextKey: currentIndex >= 0 && currentIndex < total - 1
|
||||||
|
? String(currentIndex + 1)
|
||||||
|
: currentIndex < 0
|
||||||
|
? "0"
|
||||||
|
: ""
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getPrevButton: (elements) => elements?.prevButton,
|
||||||
|
getNextButton: (elements) => elements?.nextButton,
|
||||||
|
getPositionEl: (elements) => elements?.positionEl,
|
||||||
|
formatPositionText: ({ total, currentIndex }) => {
|
||||||
|
if (total > 0 && currentIndex >= 0) {
|
||||||
|
return `${currentIndex + 1} of ${total}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total > 0 ? `${total} items` : "No items";
|
||||||
|
},
|
||||||
|
selectTarget: (targetKey) => {
|
||||||
|
const options = getAutoSequenceOptions(controls.listEl);
|
||||||
|
const targetIndex = Number(targetKey);
|
||||||
|
if (!Number.isFinite(targetIndex) || targetIndex < 0 || targetIndex >= options.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetOption = options[targetIndex];
|
||||||
|
if (!(targetOption instanceof HTMLElement)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetOption instanceof HTMLButtonElement && targetOption.disabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetOption.dispatchEvent(new MouseEvent("click", {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
view: window
|
||||||
|
}));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
afterSelect: (targetKey) => {
|
||||||
|
const options = getAutoSequenceOptions(controls.listEl);
|
||||||
|
const targetIndex = Number(targetKey);
|
||||||
|
if (!Number.isFinite(targetIndex) || targetIndex < 0 || targetIndex >= options.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetOption = options[targetIndex];
|
||||||
|
if (targetOption instanceof HTMLElement) {
|
||||||
|
targetOption.scrollIntoView({ block: "nearest" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
navigator.bind(controls);
|
||||||
|
|
||||||
|
const listObserver = new MutationObserver(() => {
|
||||||
|
navigator.sync(controls);
|
||||||
|
});
|
||||||
|
|
||||||
|
listObserver.observe(controls.listEl, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ["aria-selected", "class", "hidden", "aria-hidden"]
|
||||||
|
});
|
||||||
|
|
||||||
|
automaticNavigators.set(sectionEl, {
|
||||||
|
controls,
|
||||||
|
navigator,
|
||||||
|
listObserver
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function scanForAutomaticNavigators() {
|
||||||
|
document.querySelectorAll("section").forEach((sectionEl) => {
|
||||||
|
createAutomaticNavigatorForSection(sectionEl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function queueAutomaticNavigationScan() {
|
||||||
|
if (autoScanQueued) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
autoScanQueued = true;
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
autoScanQueued = false;
|
||||||
|
scanForAutomaticNavigators();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableAutomaticSequenceNavigation() {
|
||||||
|
if (autoNavigationEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
autoNavigationEnabled = true;
|
||||||
|
scanForAutomaticNavigators();
|
||||||
|
|
||||||
|
if (document.body && !autoScanObserver) {
|
||||||
|
autoScanObserver = new MutationObserver(() => {
|
||||||
|
queueAutomaticNavigationScan();
|
||||||
|
});
|
||||||
|
|
||||||
|
autoScanObserver.observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createSequenceNavigator(config = {}) {
|
function createSequenceNavigator(config = {}) {
|
||||||
const getElements = typeof config.getElements === "function"
|
const getElements = typeof config.getElements === "function"
|
||||||
? config.getElements
|
? config.getElements
|
||||||
@@ -184,6 +439,9 @@
|
|||||||
|
|
||||||
window.TarotSequenceNav = {
|
window.TarotSequenceNav = {
|
||||||
...(window.TarotSequenceNav || {}),
|
...(window.TarotSequenceNav || {}),
|
||||||
createSequenceNavigator
|
createSequenceNavigator,
|
||||||
|
enableAutomaticSequenceNavigation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enableAutomaticSequenceNavigation();
|
||||||
})();
|
})();
|
||||||
+6
-1
@@ -1052,6 +1052,11 @@
|
|||||||
<div class="planet-detail-heading">
|
<div class="planet-detail-heading">
|
||||||
<h2 id="alpha-detail-name">--</h2>
|
<h2 id="alpha-detail-name">--</h2>
|
||||||
<div id="alpha-detail-sub" class="planet-detail-type">Select a letter to explore</div>
|
<div id="alpha-detail-sub" class="planet-detail-type">Select a letter to explore</div>
|
||||||
|
<div class="detail-sequence-nav" aria-label="Browse letters">
|
||||||
|
<button id="alpha-detail-prev" class="detail-sequence-btn" type="button" aria-label="Previous letter">Back</button>
|
||||||
|
<div id="alpha-detail-position" class="detail-sequence-position" aria-live="polite">--</div>
|
||||||
|
<button id="alpha-detail-next" class="detail-sequence-btn" type="button" aria-label="Next letter">Next</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="alpha-detail-body" class="planet-meta-grid"></div>
|
<div id="alpha-detail-body" class="planet-meta-grid"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1354,7 +1359,7 @@
|
|||||||
<script src="app/ui-calendar-detail-panels.js?v=20260529-access-gating-02"></script>
|
<script src="app/ui-calendar-detail-panels.js?v=20260529-access-gating-02"></script>
|
||||||
<script src="app/ui-calendar-detail.js?v=20260529-access-gating-02"></script>
|
<script src="app/ui-calendar-detail.js?v=20260529-access-gating-02"></script>
|
||||||
<script src="app/ui-calendar-data.js?v=20260424-decan-ranges-01"></script>
|
<script src="app/ui-calendar-data.js?v=20260424-decan-ranges-01"></script>
|
||||||
<script src="app/ui-sequence-nav.js?v=20260528-sequence-nav-01"></script>
|
<script src="app/ui-sequence-nav.js?v=20260624-sequence-nav-auto-01"></script>
|
||||||
<script src="app/ui-calendar.js?v=20260528-sequence-nav-01"></script>
|
<script src="app/ui-calendar.js?v=20260528-sequence-nav-01"></script>
|
||||||
<script src="app/ui-holidays-data.js"></script>
|
<script src="app/ui-holidays-data.js"></script>
|
||||||
<script src="app/ui-holidays-render.js?v=20260529-access-gating-02"></script>
|
<script src="app/ui-holidays-render.js?v=20260529-access-gating-02"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user