diff --git a/controllers/akteur_controller.go b/controllers/akteur_controller.go index b7bf540..ec901fa 100644 --- a/controllers/akteur_controller.go +++ b/controllers/akteur_controller.go @@ -1,6 +1,7 @@ package controllers import ( + "slices" "strings" "github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging" @@ -26,7 +27,7 @@ func GetAgents(kgpz *xmlmodels.Library) fiber.Handler { return c.SendStatus(fiber.StatusNotFound) } return c.Render( - "/autoren/", + "/akteure/autoren/", fiber.Map{"model": agents}, ) } @@ -34,26 +35,52 @@ func GetAgents(kgpz *xmlmodels.Library) fiber.Handler { // Handle special "anonym" route if a == "anonym" { anonymAgent := viewmodels.AnonymView(kgpz) + + // Build available letters list (same logic as AgentsView) + av := make(map[string]bool) + for _, agent := range kgpz.Agents.Array { + av[strings.ToUpper(agent.ID[:1])] = true + } + availableLetters := make([]string, 0, len(av)) + for letter := range av { + availableLetters = append(availableLetters, letter) + } + slices.Sort(availableLetters) + return c.Render( - "/akteure/", + "/akteure/anonym/", fiber.Map{"model": &viewmodels.AgentsListView{ Search: "anonym", - AvailableLetters: []string{}, + AvailableLetters: availableLetters, Agents: map[string]xmlmodels.Agent{"anonym": *anonymAgent}, Sorted: []string{"anonym"}, }}, ) } - // Handle normal letter/id lookup - agents := viewmodels.AgentsView(a, kgpz) - if len(agents.Agents) == 0 { - logging.Error(nil, "No agents found for letter or id: "+a) - return c.SendStatus(fiber.StatusNotFound) + // Handle single letter (letter view) vs individual person ID (person view) + if len(a) == 1 { + // Letter view - show all people starting with this letter + agents := viewmodels.AgentsView(a, kgpz) + if len(agents.Agents) == 0 { + logging.Error(nil, "No agents found for letter: "+a) + return c.SendStatus(fiber.StatusNotFound) + } + return c.Render( + "/akteure/letter/", + fiber.Map{"model": agents}, + ) + } else { + // Individual person view - show specific person + agents := viewmodels.AgentsView(a, kgpz) + if len(agents.Agents) == 0 { + logging.Error(nil, "No agents found for id: "+a) + return c.SendStatus(fiber.StatusNotFound) + } + return c.Render( + "/akteure/person/", + fiber.Map{"model": agents}, + ) } - return c.Render( - "/akteure/", - fiber.Map{"model": agents}, - ) } -} +} \ No newline at end of file diff --git a/views/assets/scripts.js b/views/assets/scripts.js index 434f187..85980d1 100644 --- a/views/assets/scripts.js +++ b/views/assets/scripts.js @@ -1,11 +1,11 @@ -class H extends HTMLElement { +class B extends HTMLElement { constructor() { super(), this.scrollHandler = null, this.scrollTimeout = null, this.clickHandlers = [], this.manualNavigation = !1; } connectedCallback() { - setTimeout(() => { + window.ExecuteNextSettle(() => { this.initializeScrollspyAfterDelay(); - }, 100); + }); } initializeScrollspyAfterDelay() { if (this.sections = document.querySelectorAll(".author-section"), this.navLinks = document.querySelectorAll(".scrollspy-link"), this.sections.length === 0 || this.navLinks.length === 0) { @@ -25,10 +25,10 @@ class H extends HTMLElement { this.updateActiveLink(), this.updateSidebarScrollToTopButton(); }, 50); }, window.addEventListener("scroll", this.scrollHandler), this.navLinks.forEach((e) => { - const t = (n) => { - n.preventDefault(); - const i = e.getAttribute("data-target"), o = document.getElementById(i); - o && (this.updateActiveLinkImmediate(i), this.manualNavigation = !0, o.scrollIntoView({ + const t = (i) => { + i.preventDefault(); + const n = e.getAttribute("data-target"), r = document.getElementById(n); + r && (this.updateActiveLinkImmediate(n), this.manualNavigation = !0, r.scrollIntoView({ behavior: "smooth", block: "start" }), setTimeout(() => { @@ -42,15 +42,15 @@ class H extends HTMLElement { const e = document.getElementById("scrollspy-slider"), t = document.getElementById("scrollspy-nav"); if (!e || !t || e.style.opacity === "0") return; - const n = t.getBoundingClientRect(), i = parseFloat(e.style.top), o = parseFloat(e.style.height), s = i + o, l = t.scrollTop, a = l + n.height; + const i = t.getBoundingClientRect(), n = parseFloat(e.style.top), r = parseFloat(e.style.height), s = n + r, l = t.scrollTop, a = l + i.height; if (s > a) { - const c = s - n.height + 20; + const c = s - i.height + 20; t.scrollTo({ top: c, behavior: "smooth" }); - } else if (i < l) { - const c = i - 20; + } else if (n < l) { + const c = n - 20; t.scrollTo({ top: Math.max(0, c), behavior: "smooth" @@ -62,62 +62,62 @@ class H extends HTMLElement { return; const e = []; try { - this.sections.forEach((i) => { - if (!i || !i.getAttribute) return; - const o = i.getAttribute("id"), s = i.querySelector(".akteur-werke-section"), l = i.querySelector(".akteur-beitraege-section"); + this.sections.forEach((n) => { + if (!n || !n.getAttribute) return; + const r = n.getAttribute("id"), s = n.querySelector(".akteur-werke-section"), l = n.querySelector(".akteur-beitraege-section"); let a = !1; if (s) { - const c = s.getBoundingClientRect(), d = c.top < window.innerHeight, g = c.bottom > 0; - d && g && (a = !0); + const c = s.getBoundingClientRect(), d = c.top < window.innerHeight, u = c.bottom > 0; + d && u && (a = !0); } if (l && !a) { - const c = l.getBoundingClientRect(), d = c.top < window.innerHeight, g = c.bottom > 0; - d && g && (a = !0); + const c = l.getBoundingClientRect(), d = c.top < window.innerHeight, u = c.bottom > 0; + d && u && (a = !0); } if (!s && !l) { - const c = i.querySelector("div:first-child"); + const c = n.querySelector("div:first-child"); if (c) { - const d = c.getBoundingClientRect(), g = d.top >= 0, h = d.bottom <= window.innerHeight; - g && h && (a = !0); + const d = c.getBoundingClientRect(), u = d.top >= 0, h = d.bottom <= window.innerHeight; + u && h && (a = !0); } } - a && e.push(o); + a && e.push(r); }); } catch { return; } - const t = [], n = document.getElementById("scrollspy-slider"); - if (this.navLinks.forEach((i) => { - i.classList.remove("font-medium"); - const o = i.getAttribute("data-target"); - e.includes(o) && (i.classList.add("font-medium"), t.push(i)); - }), t.length > 0 && n) { - const i = document.getElementById("scrollspy-nav"), o = i.getBoundingClientRect(); + const t = [], i = document.getElementById("scrollspy-slider"); + if (this.navLinks.forEach((n) => { + n.classList.remove("font-medium"); + const r = n.getAttribute("data-target"); + e.includes(r) && (n.classList.add("font-medium"), t.push(n)); + }), t.length > 0 && i) { + const n = document.getElementById("scrollspy-nav"), r = n.getBoundingClientRect(); let s = 1 / 0, l = -1 / 0; t.forEach((c) => { - const d = c.getBoundingClientRect(), g = d.top - o.top + i.scrollTop, h = g + d.height; - s = Math.min(s, g), l = Math.max(l, h); + const d = c.getBoundingClientRect(), u = d.top - r.top + n.scrollTop, h = u + d.height; + s = Math.min(s, u), l = Math.max(l, h); }); let a = l - s; - n.style.top = `${s}px`, n.style.height = `${a}px`, n.style.opacity = "1", setTimeout(() => this.ensureMarkerVisibility(), 100); - } else n && (n.style.opacity = "0"); + i.style.top = `${s}px`, i.style.height = `${a}px`, i.style.opacity = "1", setTimeout(() => this.ensureMarkerVisibility(), 100); + } else i && (i.style.opacity = "0"); t.length > 0 && this.updateSidebarScroll(t); } updateActiveLinkImmediate(e) { if (!this.navLinks) return; const t = document.getElementById("scrollspy-slider"); try { - this.navLinks.forEach((i) => { - i && i.classList && i.classList.remove("font-medium"); + this.navLinks.forEach((n) => { + n && n.classList && n.classList.remove("font-medium"); }); } catch { return; } - const n = document.querySelector(`[data-target="${e}"]`); - if (n && (n.classList.add("font-medium"), t)) { - const i = document.getElementById("scrollspy-nav"); - if (i) { - const o = i.getBoundingClientRect(), s = n.getBoundingClientRect(), l = s.top - o.top + i.scrollTop; + const i = document.querySelector(`[data-target="${e}"]`); + if (i && (i.classList.add("font-medium"), t)) { + const n = document.getElementById("scrollspy-nav"); + if (n) { + const r = n.getBoundingClientRect(), s = i.getBoundingClientRect(), l = s.top - r.top + n.scrollTop; t.style.top = `${l}px`, t.style.height = `${s.height}px`, t.style.opacity = "1"; } } @@ -126,17 +126,17 @@ class H extends HTMLElement { if (this.manualNavigation) return; const t = document.getElementById("scrollspy-nav"); if (!t) return; - const n = e[0], i = Math.max( + const i = e[0], n = Math.max( document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight - ), o = window.innerHeight, s = i - o, l = s > 0 ? window.scrollY / s : 0, a = t.clientHeight, d = t.scrollHeight - a; + ), r = window.innerHeight, s = n - r, l = s > 0 ? window.scrollY / s : 0, a = t.clientHeight, d = t.scrollHeight - a; if (d > 0) { - const g = l * d, h = n.getBoundingClientRect(), P = t.getBoundingClientRect(), C = h.top - P.top + t.scrollTop, k = a / 2, T = C - k, m = 0.7, I = m * g + (1 - m) * T, b = Math.max(0, Math.min(d, I)), L = t.scrollTop; - Math.abs(b - L) > 10 && t.scrollTo({ - top: b, + const u = l * d, h = i.getBoundingClientRect(), C = t.getBoundingClientRect(), k = h.top - C.top + t.scrollTop, T = a / 2, I = k - T, b = 0.7, L = b * u + (1 - b) * I, w = Math.max(0, Math.min(d, L)), H = t.scrollTop; + Math.abs(w - H) > 10 && t.scrollTo({ + top: w, behavior: "smooth" }); } @@ -144,19 +144,19 @@ class H extends HTMLElement { updateSidebarScrollToTopButton() { const e = document.getElementById("sidebar-scroll-to-top"); if (!e) return; - const t = window.pageYOffset || document.documentElement.scrollTop, n = window.innerHeight; - t > n * 0.5 ? (e.classList.remove("opacity-0"), e.classList.add("opacity-100")) : (e.classList.remove("opacity-100"), e.classList.add("opacity-0")); + const t = window.pageYOffset || document.documentElement.scrollTop, i = window.innerHeight; + t > i * 0.5 ? (e.classList.remove("opacity-0"), e.classList.add("opacity-100")) : (e.classList.remove("opacity-100"), e.classList.add("opacity-0")); } cleanup() { - this.scrollHandler && (window.removeEventListener("scroll", this.scrollHandler), this.scrollHandler = null), this.scrollTimeout && (clearTimeout(this.scrollTimeout), this.scrollTimeout = null), this.clickHandlers && this.clickHandlers.length > 0 && this.clickHandlers.forEach(({ link: t, handler: n }) => { - t && n && t.removeEventListener("click", n); + this.scrollHandler && (window.removeEventListener("scroll", this.scrollHandler), this.scrollHandler = null), this.scrollTimeout && (clearTimeout(this.scrollTimeout), this.scrollTimeout = null), this.clickHandlers && this.clickHandlers.length > 0 && this.clickHandlers.forEach(({ link: t, handler: i }) => { + t && i && t.removeEventListener("click", i); }); const e = document.getElementById("scrollspy-slider"); e && (e.style.opacity = "0", e.style.height = "0"), this.sections = null, this.navLinks = null, this.clickHandlers = [], this.manualNavigation = !1; } } -customElements.define("akteure-scrollspy", H); -class B extends HTMLElement { +customElements.define("akteure-scrollspy", B); +class E extends HTMLElement { constructor() { super(), this.resizeObserver = null; } @@ -164,8 +164,8 @@ class B extends HTMLElement { detectSidebarWidth() { const e = document.querySelector('.lg\\:w-1\\/4, .lg\\:w-1\\/3, [class*="lg:w-1/"]'); if (e) { - const i = e.getBoundingClientRect().width; - return console.log("Detected sidebar width:", i, "px"), `${i}px`; + const n = e.getBoundingClientRect().width; + return console.log("Detected sidebar width:", n, "px"), `${n}px`; } const t = window.innerWidth; return t < 1024 ? "0px" : t < 1280 ? `${Math.floor(t * 0.25)}px` : `${Math.floor(t * 0.2)}px`; @@ -281,22 +281,22 @@ class B extends HTMLElement { e.style.width = t, console.log("Updated sidebar width to:", t); } } - show(e, t, n, i = !1, o = 0, s = null) { + show(e, t, i, n = !1, r = 0, s = null) { const l = this.querySelector("#single-page-image"), a = this.querySelector("#page-number"), c = this.querySelector("#page-icon"); - this.querySelector("#page-indicator"), l.src = e, l.alt = t, this.currentPageNumber = n, this.currentIsBeilage = i, this.currentPartNumber = s; - const d = this.getIssueContext(n); - if (a.innerHTML = d ? `${d}, ${n}` : `${n}`, o && n === o) { + this.querySelector("#page-indicator"), l.src = e, l.alt = t, this.currentPageNumber = i, this.currentIsBeilage = n, this.currentPartNumber = s; + const d = this.getIssueContext(i); + if (a.innerHTML = d ? `${d}, ${i}` : `${i}`, r && i === r) { a.style.position = "relative"; - const g = a.querySelector(".target-page-dot"); - g && g.remove(); + const u = a.querySelector(".target-page-dot"); + u && u.remove(); const h = document.createElement("span"); h.className = "target-page-dot absolute -top-1 -right-1 w-3 h-3 bg-red-500 rounded-full z-10", h.title = "verlinkte Seite", a.appendChild(h); } if (s !== null) c.innerHTML = `${s}. Teil`; else { - const g = this.determinePageIconType(n, i); - c.innerHTML = this.getPageIconHTML(g); + const u = this.determinePageIconType(i, n); + c.innerHTML = this.getPageIconHTML(u); } this.updateNavigationButtons(), this.style.display = "block", document.body.style.overflow = "hidden"; } @@ -308,13 +308,13 @@ class B extends HTMLElement { } // Determine page icon type based on page position and whether it's beilage determinePageIconType(e, t) { - const n = t ? '.newspaper-page-container[data-beilage="true"]' : ".newspaper-page-container:not([data-beilage])", o = Array.from(document.querySelectorAll(n)).map((a) => { + const i = t ? '.newspaper-page-container[data-beilage="true"]' : ".newspaper-page-container:not([data-beilage])", r = Array.from(document.querySelectorAll(i)).map((a) => { const c = a.getAttribute("data-page-container"); return c ? parseInt(c) : null; }).filter((a) => a !== null).sort((a, c) => a - c); - if (o.length === 0) + if (r.length === 0) return "first"; - const s = o[0], l = o[o.length - 1]; + const s = r[0], l = r[r.length - 1]; return e === s ? "first" : e === l ? "last" : e === s + 1 ? "even" : e === l - 1 ? "odd" : e % 2 === 0 ? "even" : "odd"; } // Generate page icon HTML based on type (same as Go PageIcon function) @@ -349,14 +349,14 @@ class B extends HTMLElement { } // Update navigation button visibility based on available pages updateNavigationButtons() { - const e = this.querySelector("#prev-page-btn"), t = this.querySelector("#next-page-btn"), { prevPage: n, nextPage: i } = this.getAdjacentPages(); - n !== null ? (e.disabled = !1, e.className = e.className.replace("opacity-50 cursor-not-allowed", ""), e.className = e.className.replace( + const e = this.querySelector("#prev-page-btn"), t = this.querySelector("#next-page-btn"), { prevPage: i, nextPage: n } = this.getAdjacentPages(); + i !== null ? (e.disabled = !1, e.className = e.className.replace("opacity-50 cursor-not-allowed", ""), e.className = e.className.replace( "bg-gray-50 text-gray-400", "bg-gray-100 text-gray-700" )) : (e.disabled = !0, e.className.includes("opacity-50") || (e.className += " opacity-50 cursor-not-allowed"), e.className = e.className.replace( "bg-gray-100 text-gray-700", "bg-gray-50 text-gray-400" - )), i !== null ? (t.disabled = !1, t.className = t.className.replace("opacity-50 cursor-not-allowed", ""), t.className = t.className.replace( + )), n !== null ? (t.disabled = !1, t.className = t.className.replace("opacity-50 cursor-not-allowed", ""), t.className = t.className.replace( "bg-gray-50 text-gray-400", "bg-gray-100 text-gray-700" )) : (t.disabled = !0, t.className.includes("opacity-50") || (t.className += " opacity-50 cursor-not-allowed"), t.className = t.className.replace( @@ -375,15 +375,15 @@ class B extends HTMLElement { "for", this.currentIsBeilage ? "beilage" : "main" ); - const n = t.map((l) => { + const i = t.map((l) => { const a = l.getAttribute("data-page-container"), c = a ? parseInt(a) : null; return console.log("Container page:", a, "parsed:", c), c; }).filter((l) => l !== null).sort((l, a) => l - a); - console.log("All pages found:", n), console.log("Current page:", this.currentPageNumber); - const i = n.indexOf(this.currentPageNumber); - console.log("Current index:", i); - let o = null, s = null; - return i > 0 && (o = n[i - 1]), i < n.length - 1 && (s = n[i + 1]), console.log("Adjacent pages - prev:", o, "next:", s), { prevPage: o, nextPage: s }; + console.log("All pages found:", i), console.log("Current page:", this.currentPageNumber); + const n = i.indexOf(this.currentPageNumber); + console.log("Current index:", n); + let r = null, s = null; + return n > 0 && (r = i[n - 1]), n < i.length - 1 && (s = i[n + 1]), console.log("Adjacent pages - prev:", r, "next:", s), { prevPage: r, nextPage: s }; } // Navigate to previous page goToPreviousPage() { @@ -397,20 +397,20 @@ class B extends HTMLElement { } // Navigate to a specific page navigateToPage(e) { - const t = this.currentIsBeilage ? '.newspaper-page-container[data-beilage="true"]' : ".newspaper-page-container:not([data-beilage])", n = document.querySelector( + const t = this.currentIsBeilage ? '.newspaper-page-container[data-beilage="true"]' : ".newspaper-page-container:not([data-beilage])", i = document.querySelector( `${t}[data-page-container="${e}"]` ); - if (n) { - const i = n.querySelector(".newspaper-page-image"); - if (i) { - let o = null; - this.currentPartNumber !== null && (o = this.getPartNumberForPage(e)), this.show( - i.src, - i.alt, + if (i) { + const n = i.querySelector(".newspaper-page-image"); + if (n) { + let r = null; + this.currentPartNumber !== null && (r = this.getPartNumberForPage(e)), this.show( + n.src, + n.alt, e, this.currentIsBeilage, 0, - o + r ); } } @@ -419,36 +419,36 @@ class B extends HTMLElement { getPartNumberForPage(e) { const t = document.querySelector(`[data-page-container="${e}"]`); if (t) { - const n = t.querySelector(".part-number"); - if (n) { - const i = n.textContent.match(/(\d+)\./); - if (i) - return parseInt(i[1]); + const i = t.querySelector(".part-number"); + if (i) { + const n = i.textContent.match(/(\d+)\./); + if (n) + return parseInt(n[1]); } } return null; } // Toggle sidebar visibility toggleSidebar() { - const e = this.querySelector("#sidebar-spacer"), t = this.querySelector("#sidebar-toggle-btn"), n = t.querySelector("i"), i = e.style.width, o = i === "0px" || i === "0"; - if (console.log("Current state - isCollapsed:", o), console.log("Current width:", i), o) { + const e = this.querySelector("#sidebar-spacer"), t = this.querySelector("#sidebar-toggle-btn"), i = t.querySelector("i"), n = e.style.width, r = n === "0px" || n === "0"; + if (console.log("Current state - isCollapsed:", r), console.log("Current width:", n), r) { const s = this.detectSidebarWidth(); - e.style.width = s, t.className = "w-10 h-10 bg-slate-100 hover:bg-slate-200 text-slate-700 border border-slate-300 rounded flex items-center justify-center transition-colors duration-200 cursor-pointer", n.className = "ri-sidebar-fold-line text-lg font-bold", t.title = "Inhaltsverzeichnis ausblenden", console.log("Expanding sidebar to:", s); + e.style.width = s, t.className = "w-10 h-10 bg-slate-100 hover:bg-slate-200 text-slate-700 border border-slate-300 rounded flex items-center justify-center transition-colors duration-200 cursor-pointer", i.className = "ri-sidebar-fold-line text-lg font-bold", t.title = "Inhaltsverzeichnis ausblenden", console.log("Expanding sidebar to:", s); } else - e.style.width = "0px", t.className = "w-10 h-10 bg-orange-100 hover:bg-orange-200 text-orange-700 border border-orange-300 rounded flex items-center justify-center transition-colors duration-200 cursor-pointer", n.className = "ri-sidebar-unfold-line text-lg font-bold", t.title = "Inhaltsverzeichnis einblenden", console.log("Collapsing sidebar"); + e.style.width = "0px", t.className = "w-10 h-10 bg-orange-100 hover:bg-orange-200 text-orange-700 border border-orange-300 rounded flex items-center justify-center transition-colors duration-200 cursor-pointer", i.className = "ri-sidebar-unfold-line text-lg font-bold", t.title = "Inhaltsverzeichnis einblenden", console.log("Collapsing sidebar"); console.log("New width:", e.style.width); } // Extract issue context from document title, URL, or page container getIssueContext(e) { - const t = window.location.pathname, n = t.includes("/beitrag/"); - if (n) { + const t = window.location.pathname, i = t.includes("/beitrag/"); + if (i) { const s = document.querySelector(`[data-page-container="${e}"]`); if (s) { const c = s.querySelector(".page-indicator"); if (c) { - const d = c.textContent.trim(), g = d.match(/(\d{1,2}\.\d{1,2}\.\d{4}\s+Nr\.\s+\d+)/); - if (g) - return g[1]; + const d = c.textContent.trim(), u = d.match(/(\d{1,2}\.\d{1,2}\.\d{4}\s+Nr\.\s+\d+)/); + if (u) + return u[1]; const h = d.match(/(\d{4})\s+Nr\.\s+(\d+)/); if (h) return `${h[1]} Nr. ${h[2]}`; @@ -459,28 +459,28 @@ class B extends HTMLElement { return `${a[1]} Nr. ${a[2]}`; } else return ""; - const i = t.match(/\/(\d{4})\/(\d+)/); - if (i) - return n ? `${i[1]} Nr. ${i[2]}` : ""; - const o = document.querySelector(".page-indicator"); - if (o) { - const l = o.textContent.trim().match(/(\d{4})\s+Nr\.\s+(\d+)/); + const n = t.match(/\/(\d{4})\/(\d+)/); + if (n) + return i ? `${n[1]} Nr. ${n[2]}` : ""; + const r = document.querySelector(".page-indicator"); + if (r) { + const l = r.textContent.trim().match(/(\d{4})\s+Nr\.\s+(\d+)/); if (l) return `${l[1]} Nr. ${l[2]}`; } return "KGPZ"; } } -customElements.define("single-page-viewer", B); -document.body.addEventListener("htmx:beforeRequest", function(r) { +customElements.define("single-page-viewer", E); +document.body.addEventListener("htmx:beforeRequest", function(o) { const e = document.querySelector("single-page-viewer"); e && e.style.display !== "none" && (console.log("Cleaning up single page viewer before HTMX navigation"), e.destroy()); }); window.addEventListener("beforeunload", function() { - const r = document.querySelector("single-page-viewer"); - r && r.destroy(); + const o = document.querySelector("single-page-viewer"); + o && o.destroy(); }); -class E extends HTMLElement { +class A extends HTMLElement { constructor() { super(), this.isVisible = !1, this.scrollHandler = null, this.htmxAfterSwapHandler = null; } @@ -511,8 +511,8 @@ class E extends HTMLElement { handleScroll() { const e = this.querySelector("#scroll-to-top-btn"); if (!e) return; - const t = window.pageYOffset || document.documentElement.scrollTop, n = window.innerHeight, i = t > n; - i && !this.isVisible ? (this.isVisible = !0, e.classList.remove("opacity-0", "pointer-events-none"), e.classList.add("opacity-100", "pointer-events-auto")) : !i && this.isVisible && (this.isVisible = !1, e.classList.remove("opacity-100", "pointer-events-auto"), e.classList.add("opacity-0", "pointer-events-none")); + const t = window.pageYOffset || document.documentElement.scrollTop, i = window.innerHeight, n = t > i; + n && !this.isVisible ? (this.isVisible = !0, e.classList.remove("opacity-0", "pointer-events-none"), e.classList.add("opacity-100", "pointer-events-auto")) : !n && this.isVisible && (this.isVisible = !1, e.classList.remove("opacity-100", "pointer-events-auto"), e.classList.add("opacity-0", "pointer-events-none")); } scrollToTop() { window.scrollTo({ @@ -521,30 +521,30 @@ class E extends HTMLElement { }); } } -customElements.define("scroll-to-top-button", E); +customElements.define("scroll-to-top-button", A); window.currentPageContainers = window.currentPageContainers || []; window.currentActiveIndex = window.currentActiveIndex || 0; window.pageObserver = window.pageObserver || null; -function A(r, e, t, n = null) { - let i = document.querySelector("single-page-viewer"); - i || (i = document.createElement("single-page-viewer"), document.body.appendChild(i)); - const o = r.closest('[data-beilage="true"]') !== null, s = window.templateData && window.templateData.targetPage ? window.templateData.targetPage : 0; - i.show(r.src, r.alt, e, o, s, n); +function $(o, e, t, i = null) { + let n = document.querySelector("single-page-viewer"); + n || (n = document.createElement("single-page-viewer"), document.body.appendChild(n)); + const r = o.closest('[data-beilage="true"]') !== null, s = window.templateData && window.templateData.targetPage ? window.templateData.targetPage : 0; + n.show(o.src, o.alt, e, r, s, i); } -function x() { +function S() { document.getElementById("pageModal").classList.add("hidden"); } -function $() { +function N() { if (window.pageObserver && (window.pageObserver.disconnect(), window.pageObserver = null), window.currentPageContainers = Array.from(document.querySelectorAll(".newspaper-page-container")), window.currentActiveIndex = 0, p(), document.querySelector(".newspaper-page-container")) { let e = /* @__PURE__ */ new Set(); window.pageObserver = new IntersectionObserver( (t) => { - if (t.forEach((n) => { - const i = window.currentPageContainers.indexOf(n.target); - i !== -1 && (n.isIntersecting ? e.add(i) : e.delete(i)); + if (t.forEach((i) => { + const n = window.currentPageContainers.indexOf(i.target); + n !== -1 && (i.isIntersecting ? e.add(n) : e.delete(n)); }), e.size > 0) { - const i = Array.from(e).sort((o, s) => o - s)[0]; - i !== window.currentActiveIndex && (window.currentActiveIndex = i, p()); + const n = Array.from(e).sort((r, s) => r - s)[0]; + n !== window.currentActiveIndex && (window.currentActiveIndex = n, p()); } }, { @@ -555,43 +555,21 @@ function $() { }); } } -function N() { +function q() { if (window.currentActiveIndex > 0) { - let r = -1; + let o = -1; const e = []; - window.currentPageContainers.forEach((n, i) => { - const o = n.getBoundingClientRect(), s = window.innerHeight, l = Math.max(o.top, 0), a = Math.min(o.bottom, s), c = Math.max(0, a - l), d = o.height; - c / d >= 0.3 && e.push(i); + window.currentPageContainers.forEach((i, n) => { + const r = i.getBoundingClientRect(), s = window.innerHeight, l = Math.max(r.top, 0), a = Math.min(r.bottom, s), c = Math.max(0, a - l), d = r.height; + c / d >= 0.3 && e.push(n); }); const t = Math.min(...e); - for (let n = t - 1; n >= 0; n--) - if (!e.includes(n)) { - r = n; + for (let i = t - 1; i >= 0; i--) + if (!e.includes(i)) { + o = i; break; } - r === -1 && t > 0 && (r = t - 1), r >= 0 && (window.currentActiveIndex = r, window.currentPageContainers[window.currentActiveIndex].scrollIntoView({ - behavior: "smooth", - block: "start" - }), setTimeout(() => { - p(); - }, 100)); - } -} -function q() { - if (window.currentActiveIndex < window.currentPageContainers.length - 1) { - let r = -1; - const e = []; - window.currentPageContainers.forEach((n, i) => { - const o = n.getBoundingClientRect(), s = window.innerHeight, l = Math.max(o.top, 0), a = Math.min(o.bottom, s), c = Math.max(0, a - l), d = o.height; - c / d >= 0.3 && e.push(i); - }); - const t = Math.max(...e); - for (let n = t + 1; n < window.currentPageContainers.length; n++) - if (!e.includes(n)) { - r = n; - break; - } - r === -1 && t < window.currentPageContainers.length - 1 && (r = t + 1), r >= 0 && r < window.currentPageContainers.length && (window.currentActiveIndex = r, window.currentPageContainers[window.currentActiveIndex].scrollIntoView({ + o === -1 && t > 0 && (o = t - 1), o >= 0 && (window.currentActiveIndex = o, window.currentPageContainers[window.currentActiveIndex].scrollIntoView({ behavior: "smooth", block: "start" }), setTimeout(() => { @@ -600,7 +578,29 @@ function q() { } } function M() { - if (S()) { + if (window.currentActiveIndex < window.currentPageContainers.length - 1) { + let o = -1; + const e = []; + window.currentPageContainers.forEach((i, n) => { + const r = i.getBoundingClientRect(), s = window.innerHeight, l = Math.max(r.top, 0), a = Math.min(r.bottom, s), c = Math.max(0, a - l), d = r.height; + c / d >= 0.3 && e.push(n); + }); + const t = Math.max(...e); + for (let i = t + 1; i < window.currentPageContainers.length; i++) + if (!e.includes(i)) { + o = i; + break; + } + o === -1 && t < window.currentPageContainers.length - 1 && (o = t + 1), o >= 0 && o < window.currentPageContainers.length && (window.currentActiveIndex = o, window.currentPageContainers[window.currentActiveIndex].scrollIntoView({ + behavior: "smooth", + block: "start" + }), setTimeout(() => { + p(); + }, 100)); + } +} +function R() { + if (P()) { const e = document.querySelector("#newspaper-content .newspaper-page-container"); e && e.scrollIntoView({ behavior: "smooth", @@ -614,13 +614,13 @@ function M() { }); } } -function S() { - const r = []; +function P() { + const o = []; window.currentPageContainers.forEach((e, t) => { - const n = e.getBoundingClientRect(), i = window.innerHeight, o = Math.max(n.top, 0), s = Math.min(n.bottom, i), l = Math.max(0, s - o), a = n.height; - l / a >= 0.3 && r.push(t); + const i = e.getBoundingClientRect(), n = window.innerHeight, r = Math.max(i.top, 0), s = Math.min(i.bottom, n), l = Math.max(0, s - r), a = i.height; + l / a >= 0.3 && o.push(t); }); - for (const e of r) { + for (const e of o) { const t = window.currentPageContainers[e]; if (t && t.id && t.id.includes("beilage-")) return !0; @@ -628,76 +628,76 @@ function S() { return !1; } function p() { - const r = document.getElementById("prevPageBtn"), e = document.getElementById("nextPageBtn"), t = document.getElementById("beilageBtn"); - if (r && (window.currentActiveIndex <= 0 ? r.style.display = "none" : r.style.display = "flex"), e && (window.currentActiveIndex >= window.currentPageContainers.length - 1 ? e.style.display = "none" : e.style.display = "flex"), t) { - const n = S(), i = t.querySelector("i"); - n ? (t.title = "Zur Hauptausgabe", t.className = "w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-gray-100 hover:bg-gray-200 text-gray-700 hover:text-gray-800 border border-gray-300 transition-colors duration-200 flex items-center justify-center cursor-pointer", i && (i.className = "ri-file-text-line text-lg lg:text-xl")) : (t.title = "Zu Beilage", t.className = "w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-amber-100 hover:bg-amber-200 text-amber-700 hover:text-amber-800 border border-amber-300 transition-colors duration-200 flex items-center justify-center cursor-pointer", i && (i.className = "ri-attachment-line text-lg lg:text-xl")); + const o = document.getElementById("prevPageBtn"), e = document.getElementById("nextPageBtn"), t = document.getElementById("beilageBtn"); + if (o && (window.currentActiveIndex <= 0 ? o.style.display = "none" : o.style.display = "flex"), e && (window.currentActiveIndex >= window.currentPageContainers.length - 1 ? e.style.display = "none" : e.style.display = "flex"), t) { + const i = P(), n = t.querySelector("i"); + i ? (t.title = "Zur Hauptausgabe", t.className = "w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-gray-100 hover:bg-gray-200 text-gray-700 hover:text-gray-800 border border-gray-300 transition-colors duration-200 flex items-center justify-center cursor-pointer", n && (n.className = "ri-file-text-line text-lg lg:text-xl")) : (t.title = "Zu Beilage", t.className = "w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-amber-100 hover:bg-amber-200 text-amber-700 hover:text-amber-800 border border-amber-300 transition-colors duration-200 flex items-center justify-center cursor-pointer", n && (n.className = "ri-attachment-line text-lg lg:text-xl")); } } -function R() { - const r = document.getElementById("shareLinkBtn"); +function z() { + const o = document.getElementById("shareLinkBtn"); let e = ""; if (window.currentActiveIndex !== void 0 && window.currentPageContainers && window.currentPageContainers[window.currentActiveIndex]) { - const i = window.currentPageContainers[window.currentActiveIndex].querySelector("[data-page]"); - i && (e = `/${i.getAttribute("data-page")}`); + const n = window.currentPageContainers[window.currentActiveIndex].querySelector("[data-page]"); + n && (e = `/${n.getAttribute("data-page")}`); } const t = window.location.origin + window.location.pathname + e; navigator.share ? navigator.share({ title: document.title, url: t - }).catch((n) => { - w(t, r); - }) : w(t, r); + }).catch((i) => { + y(t, o); + }) : y(t, o); } -function w(r, e) { +function y(o, e) { if (navigator.clipboard) - navigator.clipboard.writeText(r).then(() => { - u(e, "Link kopiert!"); + navigator.clipboard.writeText(o).then(() => { + g(e, "Link kopiert!"); }).catch((t) => { - u(e, "Kopieren fehlgeschlagen"); + g(e, "Kopieren fehlgeschlagen"); }); else { const t = document.createElement("textarea"); - t.value = r, document.body.appendChild(t), t.select(); + t.value = o, document.body.appendChild(t), t.select(); try { - const n = document.execCommand("copy"); - u(e, n ? "Link kopiert!" : "Kopieren fehlgeschlagen"); + const i = document.execCommand("copy"); + g(e, i ? "Link kopiert!" : "Kopieren fehlgeschlagen"); } catch { - u(e, "Kopieren fehlgeschlagen"); + g(e, "Kopieren fehlgeschlagen"); } finally { document.body.removeChild(t); } } } -function z() { - const r = document.getElementById("citationBtn"), e = document.title || "KGPZ"; +function V() { + const o = document.getElementById("citationBtn"), e = document.title || "KGPZ"; let t = window.location.origin + window.location.pathname; t.includes("#") && (t = t.split("#")[0]); - const n = (/* @__PURE__ */ new Date()).toLocaleDateString("de-DE"), i = `Königsberger Gelehrte und Politische Zeitung (KGPZ). ${e}. Digital verfügbar unter: ${t} (Zugriff: ${n}).`; + const i = (/* @__PURE__ */ new Date()).toLocaleDateString("de-DE"), n = `Königsberger Gelehrte und Politische Zeitung (KGPZ). ${e}. Digital verfügbar unter: ${t} (Zugriff: ${i}).`; if (navigator.clipboard) - navigator.clipboard.writeText(i).then(() => { - u(r, "Zitation kopiert!"); - }).catch((o) => { - u(r, "Kopieren fehlgeschlagen"); + navigator.clipboard.writeText(n).then(() => { + g(o, "Zitation kopiert!"); + }).catch((r) => { + g(o, "Kopieren fehlgeschlagen"); }); else { - const o = document.createElement("textarea"); - o.value = i, document.body.appendChild(o), o.select(); + const r = document.createElement("textarea"); + r.value = n, document.body.appendChild(r), r.select(); try { const s = document.execCommand("copy"); - u(r, s ? "Zitation kopiert!" : "Kopieren fehlgeschlagen"); + g(o, s ? "Zitation kopiert!" : "Kopieren fehlgeschlagen"); } catch { - u(r, "Kopieren fehlgeschlagen"); + g(o, "Kopieren fehlgeschlagen"); } finally { - document.body.removeChild(o); + document.body.removeChild(r); } } } -function u(r, e) { +function g(o, e) { const t = document.querySelector(".simple-popup"); t && t.remove(); - const n = document.createElement("div"); - n.className = "simple-popup", n.textContent = e, n.style.cssText = ` + const i = document.createElement("div"); + i.className = "simple-popup", i.textContent = e, i.style.cssText = ` position: fixed; background: #374151; color: white; @@ -711,105 +711,105 @@ function u(r, e) { transition: opacity 0.2s ease; white-space: nowrap; `; - const i = r.getBoundingClientRect(), o = window.innerHeight, s = window.innerWidth; - let l = i.left - 10, a = i.bottom + 8; + const n = o.getBoundingClientRect(), r = window.innerHeight, s = window.innerWidth; + let l = n.left - 10, a = n.bottom + 8; const c = 120, d = 32; - l + c > s && (l = i.right - c + 10), a + d > o && (a = i.top - d - 8), n.style.left = Math.max(5, l) + "px", n.style.top = Math.max(5, a) + "px", document.body.appendChild(n), setTimeout(() => { - n.style.opacity = "1"; + l + c > s && (l = n.right - c + 10), a + d > r && (a = n.top - d - 8), i.style.left = Math.max(5, l) + "px", i.style.top = Math.max(5, a) + "px", document.body.appendChild(i), setTimeout(() => { + i.style.opacity = "1"; }, 10), setTimeout(() => { - n.style.opacity = "0", setTimeout(() => { - n.parentNode && n.remove(); + i.style.opacity = "0", setTimeout(() => { + i.parentNode && i.remove(); }, 200); }, 2e3); } -function V(r, e, t = !1) { - let n = ""; +function O(o, e, t = !1) { + let i = ""; if (t) - n = window.location.origin + window.location.pathname + `#beilage-1-page-${r}`; + i = window.location.origin + window.location.pathname + `#beilage-1-page-${o}`; else { - const o = window.location.pathname.split("/"); - if (o.length >= 3) { - const s = o[1], l = o[2]; - n = `${window.location.origin}/${s}/${l}/${r}`; + const r = window.location.pathname.split("/"); + if (r.length >= 3) { + const s = r[1], l = r[2]; + i = `${window.location.origin}/${s}/${l}/${o}`; } else - n = window.location.origin + window.location.pathname + `/${r}`; + i = window.location.origin + window.location.pathname + `/${o}`; } - const i = n; + const n = i; if (navigator.clipboard) - navigator.clipboard.writeText(i).then(() => { - u(e, "Link kopiert!"); - }).catch((o) => { - u(e, "Kopieren fehlgeschlagen"); + navigator.clipboard.writeText(n).then(() => { + g(e, "Link kopiert!"); + }).catch((r) => { + g(e, "Kopieren fehlgeschlagen"); }); else { - const o = document.createElement("textarea"); - o.value = i, document.body.appendChild(o), o.select(); + const r = document.createElement("textarea"); + r.value = n, document.body.appendChild(r), r.select(); try { const s = document.execCommand("copy"); - u(e, s ? "Link kopiert!" : "Kopieren fehlgeschlagen"); + g(e, s ? "Link kopiert!" : "Kopieren fehlgeschlagen"); } catch { - u(e, "Kopieren fehlgeschlagen"); + g(e, "Kopieren fehlgeschlagen"); } finally { - document.body.removeChild(o); + document.body.removeChild(r); } } } -function O(r, e) { - const t = document.title || "KGPZ", n = window.location.pathname.split("/"); - let i; - if (n.length >= 3) { - const a = n[1], c = n[2]; - i = `${window.location.origin}/${a}/${c}/${r}`; +function D(o, e) { + const t = document.title || "KGPZ", i = window.location.pathname.split("/"); + let n; + if (i.length >= 3) { + const a = i[1], c = i[2]; + n = `${window.location.origin}/${a}/${c}/${o}`; } else - i = `${window.location.origin}${window.location.pathname}/${r}`; - const o = i, s = (/* @__PURE__ */ new Date()).toLocaleDateString("de-DE"), l = `Königsberger Gelehrte und Politische Zeitung (KGPZ). ${t}, Seite ${r}. Digital verfügbar unter: ${o} (Zugriff: ${s}).`; + n = `${window.location.origin}${window.location.pathname}/${o}`; + const r = n, s = (/* @__PURE__ */ new Date()).toLocaleDateString("de-DE"), l = `Königsberger Gelehrte und Politische Zeitung (KGPZ). ${t}, Seite ${o}. Digital verfügbar unter: ${r} (Zugriff: ${s}).`; if (navigator.clipboard) navigator.clipboard.writeText(l).then(() => { - u(e, "Zitation kopiert!"); + g(e, "Zitation kopiert!"); }).catch((a) => { - u(e, "Kopieren fehlgeschlagen"); + g(e, "Kopieren fehlgeschlagen"); }); else { const a = document.createElement("textarea"); a.value = l, document.body.appendChild(a), a.select(); try { const c = document.execCommand("copy"); - u(e, c ? "Zitation kopiert!" : "Kopieren fehlgeschlagen"); + g(e, c ? "Zitation kopiert!" : "Kopieren fehlgeschlagen"); } catch { - u(e, "Kopieren fehlgeschlagen"); + g(e, "Kopieren fehlgeschlagen"); } finally { document.body.removeChild(a); } } } -function y() { - $(), window.addEventListener("scroll", function() { +function v() { + N(), window.addEventListener("scroll", function() { clearTimeout(window.scrollTimeout), window.scrollTimeout = setTimeout(() => { p(); }, 50); - }), document.addEventListener("keydown", function(r) { - r.key === "Escape" && x(); + }), document.addEventListener("keydown", function(o) { + o.key === "Escape" && S(); }); } function f() { - const r = window.location.pathname; + const o = window.location.pathname; document.querySelectorAll(".citation-link[data-citation-url]").forEach((t) => { - const n = t.getAttribute("data-citation-url"); - let i = !1; - if (n === r) - i = !0; + const i = t.getAttribute("data-citation-url"); + let n = !1; + if (i === o) + n = !0; else { - const o = r.match(/^\/(\d{4})\/(\d+)(?:\/(\d+))?$/), s = n.match(/^\/(\d{4})\/(\d+)$/); - if (o && s) { - const [, l, a, c] = o, [, d, g] = s; - l === d && a === g && (i = !0); + const r = o.match(/^\/(\d{4})\/(\d+)(?:\/(\d+))?$/), s = i.match(/^\/(\d{4})\/(\d+)$/); + if (r && s) { + const [, l, a, c] = r, [, d, u] = s; + l === d && a === u && (n = !0); } } - i ? (t.classList.add("text-red-700", "pointer-events-none"), t.setAttribute("aria-current", "page")) : (t.classList.remove("text-red-700", "pointer-events-none"), t.removeAttribute("aria-current")); + n ? (t.classList.add("text-red-700", "pointer-events-none"), t.setAttribute("aria-current", "page")) : (t.classList.remove("text-red-700", "pointer-events-none"), t.removeAttribute("aria-current")); }); } -function v() { - const r = window.location.pathname, e = document.body; +function x() { + const o = window.location.pathname, e = document.body; e.classList.remove( "page-akteure", "page-ausgabe", @@ -818,27 +818,41 @@ function v() { "page-kategorie", "page-piece", "page-edition" - ), r.includes("/akteure/") || r.includes("/autoren") ? e.classList.add("page-akteure") : r.match(/\/\d{4}\/\d+/) ? e.classList.add("page-ausgabe") : r.includes("/search") || r.includes("/suche") ? e.classList.add("page-search") : r.includes("/ort/") ? e.classList.add("page-ort") : r.includes("/kategorie/") ? e.classList.add("page-kategorie") : r.includes("/beitrag/") ? e.classList.add("page-piece") : r.includes("/edition") && e.classList.add("page-edition"); + ), o.includes("/akteure/") || o.includes("/autoren") ? e.classList.add("page-akteure") : o.match(/\/\d{4}\/\d+/) ? e.classList.add("page-ausgabe") : o.includes("/search") || o.includes("/suche") ? e.classList.add("page-search") : o.includes("/ort/") ? e.classList.add("page-ort") : o.includes("/kategorie/") ? e.classList.add("page-kategorie") : o.includes("/beitrag/") ? e.classList.add("page-piece") : o.includes("/edition") && e.classList.add("page-edition"); } -window.enlargePage = A; -window.closeModal = x; -window.scrollToPreviousPage = N; -window.scrollToNextPage = q; -window.scrollToBeilage = M; -window.shareCurrentPage = R; -window.generateCitation = z; -window.copyPagePermalink = V; -window.generatePageCitation = O; +let m = []; +window.ExecuteNextSettle = function(o) { + typeof o == "function" && m.push(o); +}; function K() { - v(), f(), document.querySelector(".newspaper-page-container") && y(); - let r = function(t) { - v(), f(), setTimeout(() => { - document.querySelector(".newspaper-page-container") && y(); + for (; m.length > 0; ) { + const o = m.shift(); + try { + o(); + } catch (e) { + console.error("Error executing settle queue function:", e); + } + } +} +window.enlargePage = $; +window.closeModal = S; +window.scrollToPreviousPage = q; +window.scrollToNextPage = M; +window.scrollToBeilage = R; +window.shareCurrentPage = z; +window.generateCitation = V; +window.copyPagePermalink = O; +window.generatePageCitation = D; +function W() { + x(), f(), document.querySelector(".newspaper-page-container") && v(); + let o = function(t) { + x(), f(), K(), setTimeout(() => { + document.querySelector(".newspaper-page-container") && v(); }, 50); }, e = function(t) { }; - document.body.addEventListener("htmx:afterSettle", r), document.body.addEventListener("htmx:afterSettle", f), document.body.addEventListener("htmx:beforeRequest", e); + document.body.addEventListener("htmx:afterSettle", o), document.body.addEventListener("htmx:afterSettle", f), document.body.addEventListener("htmx:beforeRequest", e); } export { - K as setup + W as setup }; diff --git a/views/routes/akteure/anonym/body.gohtml b/views/routes/akteure/anonym/body.gohtml new file mode 100644 index 0000000..8fd3329 --- /dev/null +++ b/views/routes/akteure/anonym/body.gohtml @@ -0,0 +1,14 @@ +
+
+ + {{ template "_alphabet_nav" .model }} +
+ + +
+ {{ range $_, $id := $.model.Sorted }} + {{ $a := index $.model.Agents $id }} + {{ template "_akteur" $a }} + {{ end }} +
+
\ No newline at end of file diff --git a/views/routes/akteure/anonym/head.gohtml b/views/routes/akteure/anonym/head.gohtml new file mode 100644 index 0000000..b1bc243 --- /dev/null +++ b/views/routes/akteure/anonym/head.gohtml @@ -0,0 +1,3 @@ + + KGPZ – Anonyme Werke + \ No newline at end of file diff --git a/views/routes/akteure/autoren/body.gohtml b/views/routes/akteure/autoren/body.gohtml new file mode 100644 index 0000000..f8541bd --- /dev/null +++ b/views/routes/akteure/autoren/body.gohtml @@ -0,0 +1,20 @@ +
+
+ {{ template "_header_with_toggle" .model }} +
+ + +
+ {{ template "_scrollspy_layout" .model }} + + +
+ {{ range $_, $id := $.model.Sorted }} + {{ $a := index $.model.Agents $id }} +
+ {{ template "_akteur" $a }} +
+ {{ end }} +
+
+
\ No newline at end of file diff --git a/views/routes/autoren/head.gohtml b/views/routes/akteure/autoren/head.gohtml similarity index 100% rename from views/routes/autoren/head.gohtml rename to views/routes/akteure/autoren/head.gohtml diff --git a/views/routes/akteure/body.gohtml b/views/routes/akteure/body.gohtml deleted file mode 100644 index 66270e6..0000000 --- a/views/routes/akteure/body.gohtml +++ /dev/null @@ -1,104 +0,0 @@ -{{ if ne (len .model.Search) 1 }} - {{ $agent := index $.model.Agents .model.Search }} - {{ if not $agent }} -
-
-
- - Person nicht gefunden: {{ .model.Search }} -
-
-
- {{ else }} -
-
-
- {{ if eq $agent.ID "anonym" }} - - - A - - {{ else }} - {{ $letter := Upper (FirstLetter $agent.ID) }} - - - {{ $letter }} - - {{ end }} -
- {{ template "_akteur" $agent }} -
-
- {{ end }} - -{{ else }} -
-
- -
- {{ if eq .model.Search "autoren" }} -

Autor:innen

-

Personen, die Beiträge in der Zeitung verfasst haben

- {{ else }} -

Personen & Körperschaften

-

Verzeichnis aller in der Zeitung erwähnten Personen und Institutionen

- {{ end }} - - -
- -
-
- - - {{ if ne .model.Search "autoren" }} -
-
-
- {{ range $_, $l := .model.AvailableLetters }} - {{ if eq $l (Upper $.model.Search) }} - - {{ $l }} - {{ else }} - - {{ $l }} - {{ end }} - {{ end }} - - | - {{ if eq $.model.Search "anonym" }} - anonym - {{ else }} - anonym - {{ end }} -
-
-
- {{ end }} -
- - -
- - {{ template "_scrollspy_layout" .model }} - - -
- {{ range $_, $id := $.model.Sorted }} - {{ $a := index $.model.Agents $id }} -
- {{ template "_akteur" $a }} -
- {{ end }} -
-
-{{ end }} diff --git a/views/routes/akteure/components/_alphabet_nav.gohtml b/views/routes/akteure/components/_alphabet_nav.gohtml new file mode 100644 index 0000000..c500e7c --- /dev/null +++ b/views/routes/akteure/components/_alphabet_nav.gohtml @@ -0,0 +1,23 @@ +{{- /* Shared alphabet navigation component - A-Z letters plus anonym link */ -}} +
+
+
+ {{ range $_, $l := .AvailableLetters }} + {{ if eq $l (Upper $.Search) }} + + {{ $l }} + {{ else }} + + {{ $l }} + {{ end }} + {{ end }} + + | + {{ if eq $.Search "anonym" }} + anonym + {{ else }} + anonym + {{ end }} +
+
+
\ No newline at end of file diff --git a/views/routes/akteure/components/_back_navigation.gohtml b/views/routes/akteure/components/_back_navigation.gohtml new file mode 100644 index 0000000..a91896b --- /dev/null +++ b/views/routes/akteure/components/_back_navigation.gohtml @@ -0,0 +1,15 @@ +{{- /* Shared back navigation for individual person pages */ -}} +
+ {{ if eq .ID "anonym" }} + + + A + + {{ else }} + {{ $letter := Upper (FirstLetter .ID) }} + + + {{ $letter }} + + {{ end }} +
\ No newline at end of file diff --git a/views/routes/akteure/components/_header_with_toggle.gohtml b/views/routes/akteure/components/_header_with_toggle.gohtml new file mode 100644 index 0000000..5b936c3 --- /dev/null +++ b/views/routes/akteure/components/_header_with_toggle.gohtml @@ -0,0 +1,25 @@ +{{- /* Shared header with author toggle checkbox */ -}} + +
+ {{ if eq .Search "autoren" }} +

Autor:innen

+

Personen, die Beiträge in der Zeitung verfasst haben

+ {{ else }} +

Personen & Körperschaften

+

Verzeichnis aller in der Zeitung erwähnten Personen und Institutionen

+ {{ end }} + + +
+ +
+
\ No newline at end of file diff --git a/views/routes/akteure/head.gohtml b/views/routes/akteure/head.gohtml deleted file mode 100644 index 248587d..0000000 --- a/views/routes/akteure/head.gohtml +++ /dev/null @@ -1,16 +0,0 @@ - - KGPZ – - {{ if eq .model.Search "autoren" }} - Autoren - {{ else if ne (len .model.Search) 1 }} - {{ $agent := index .model.Agents .model.Search }} - {{ if $agent }} - {{ index $agent.Names 0 }} - {{ else }} - Person nicht gefunden - {{ end }} - {{ else }} - Personen & Körperschaften: - {{ Upper .model.Search }} - {{ end }} - diff --git a/views/routes/akteure/letter/body.gohtml b/views/routes/akteure/letter/body.gohtml new file mode 100644 index 0000000..200071d --- /dev/null +++ b/views/routes/akteure/letter/body.gohtml @@ -0,0 +1,23 @@ +
+
+ {{ template "_header_with_toggle" .model }} + + + {{ template "_alphabet_nav" .model }} +
+ + +
+ {{ template "_scrollspy_layout" .model }} + + +
+ {{ range $_, $id := $.model.Sorted }} + {{ $a := index $.model.Agents $id }} +
+ {{ template "_akteur" $a }} +
+ {{ end }} +
+
+
\ No newline at end of file diff --git a/views/routes/akteure/letter/head.gohtml b/views/routes/akteure/letter/head.gohtml new file mode 100644 index 0000000..6c525b3 --- /dev/null +++ b/views/routes/akteure/letter/head.gohtml @@ -0,0 +1,3 @@ + + KGPZ – Personen & Körperschaften: {{ Upper .model.Search }} + \ No newline at end of file diff --git a/views/routes/akteure/person/body.gohtml b/views/routes/akteure/person/body.gohtml new file mode 100644 index 0000000..877715d --- /dev/null +++ b/views/routes/akteure/person/body.gohtml @@ -0,0 +1,18 @@ +{{ $agent := index $.model.Agents .model.Search }} +{{ if not $agent }} +
+
+
+ + Person nicht gefunden: {{ .model.Search }} +
+
+
+{{ else }} +
+
+ {{ template "_back_navigation" $agent }} + {{ template "_akteur" $agent }} +
+
+{{ end }} \ No newline at end of file diff --git a/views/routes/akteure/person/head.gohtml b/views/routes/akteure/person/head.gohtml new file mode 100644 index 0000000..453ac26 --- /dev/null +++ b/views/routes/akteure/person/head.gohtml @@ -0,0 +1,9 @@ +{{ $agent := index .model.Agents .model.Search }} + + KGPZ – + {{ if $agent }} + {{ index $agent.Names 0 }} + {{ else }} + Person nicht gefunden + {{ end }} + \ No newline at end of file diff --git a/views/routes/autoren/body.gohtml b/views/routes/autoren/body.gohtml deleted file mode 100644 index 067475e..0000000 --- a/views/routes/autoren/body.gohtml +++ /dev/null @@ -1,39 +0,0 @@ -
-
- -
-

Autor:innen

-

Personen, die Beiträge in der Zeitung verfasst haben

- - -
- -
-
-
- - -
- - {{ template "_scrollspy_layout" .model }} - - -
- {{ range $_, $id := $.model.Sorted }} - {{ $a := index $.model.Agents $id }} -
- {{ template "_akteur" $a }} -
- {{ end }} -
-
-
diff --git a/views/transform/akteure.js b/views/transform/akteure.js index 3ee858b..68c7699 100644 --- a/views/transform/akteure.js +++ b/views/transform/akteure.js @@ -13,9 +13,9 @@ export class AkteureScrollspy extends HTMLElement { connectedCallback() { // Small delay to ensure DOM is fully rendered after HTMX swap - setTimeout(() => { + window.ExecuteNextSettle(() => { this.initializeScrollspyAfterDelay(); - }, 100); + }); } initializeScrollspyAfterDelay() { diff --git a/views/transform/main.js b/views/transform/main.js index 445e568..395cbde 100644 --- a/views/transform/main.js +++ b/views/transform/main.js @@ -90,6 +90,28 @@ function applyPageBackdrop() { } } +// Function queue system for HTMX settle events +let settleQueue = []; + +// Global function to register functions for next settle event +window.ExecuteNextSettle = function(fn) { + if (typeof fn === 'function') { + settleQueue.push(fn); + } +}; + +// Execute and clear the queue +function executeSettleQueue() { + while (settleQueue.length > 0) { + const fn = settleQueue.shift(); + try { + fn(); + } catch (error) { + console.error('Error executing settle queue function:', error); + } + } +} + // Export functions for global access window.enlargePage = enlargePage; window.closeModal = closeModal; @@ -123,6 +145,9 @@ function setup() { // Update citation links after navigation updateCitationLinks(); + // Execute all queued functions + executeSettleQueue(); + // Use shorter delay since afterSettle ensures DOM is ready setTimeout(() => { if (document.querySelector(".newspaper-page-container")) {