mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-29 17:15:31 +00:00
+Startseite u. Suche Baic styling
This commit is contained in:
@@ -19,11 +19,15 @@ export class InhaltsverzeichnisScrollspy extends HTMLElement {
|
||||
this.singlePageViewerActive = false;
|
||||
this.singlePageViewerCurrentPage = null; // Track which page is currently viewed in single page mode
|
||||
this.boundHandleSinglePageViewer = this.handleSinglePageViewer.bind(this);
|
||||
this.eventListenersAttached = false; // Track if global event listeners are attached
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.setupScrollspy();
|
||||
this.setupSinglePageViewerDetection();
|
||||
// Use requestAnimationFrame to ensure DOM is fully settled after HTMX content swap
|
||||
requestAnimationFrame(() => {
|
||||
this.setupScrollspy();
|
||||
this.setupSinglePageViewerDetection();
|
||||
});
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
@@ -35,9 +39,27 @@ export class InhaltsverzeichnisScrollspy extends HTMLElement {
|
||||
const newspaperPageContainers = document.querySelectorAll('.newspaper-page-container[data-page-container]');
|
||||
|
||||
if (newspaperPageContainers.length === 0) {
|
||||
return; // No page containers found
|
||||
// No page containers found initially - retry after a short delay for HTMX content
|
||||
setTimeout(() => {
|
||||
const retryContainers = document.querySelectorAll('.newspaper-page-container[data-page-container]');
|
||||
if (retryContainers.length > 0) {
|
||||
this.initializeScrollspy(retryContainers);
|
||||
}
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
this.initializeScrollspy(newspaperPageContainers);
|
||||
}
|
||||
|
||||
initializeScrollspy(newspaperPageContainers) {
|
||||
|
||||
// Clear existing state to prevent conflicts during HTMX navigation
|
||||
if (this.pageObserver) {
|
||||
this.pageObserver.disconnect();
|
||||
}
|
||||
this.pageContainers.clear();
|
||||
|
||||
// Map page containers to their corresponding Inhaltsverzeichnis entries
|
||||
newspaperPageContainers.forEach(container => {
|
||||
const pageNumber = container.getAttribute('data-page-container');
|
||||
@@ -236,10 +258,13 @@ export class InhaltsverzeichnisScrollspy extends HTMLElement {
|
||||
}
|
||||
|
||||
setupSinglePageViewerDetection() {
|
||||
// Listen for single page viewer events
|
||||
document.addEventListener('singlepageviewer:opened', this.boundHandleSinglePageViewer);
|
||||
document.addEventListener('singlepageviewer:closed', this.boundHandleSinglePageViewer);
|
||||
document.addEventListener('singlepageviewer:pagechanged', this.boundHandleSinglePageViewer);
|
||||
// Only attach event listeners if not already attached
|
||||
if (!this.eventListenersAttached) {
|
||||
document.addEventListener('singlepageviewer:opened', this.boundHandleSinglePageViewer);
|
||||
document.addEventListener('singlepageviewer:closed', this.boundHandleSinglePageViewer);
|
||||
document.addEventListener('singlepageviewer:pagechanged', this.boundHandleSinglePageViewer);
|
||||
this.eventListenersAttached = true;
|
||||
}
|
||||
|
||||
// Check initial state
|
||||
this.checkSinglePageViewerState();
|
||||
@@ -302,9 +327,13 @@ export class InhaltsverzeichnisScrollspy extends HTMLElement {
|
||||
this.pageObserver = null;
|
||||
}
|
||||
|
||||
document.removeEventListener('singlepageviewer:opened', this.boundHandleSinglePageViewer);
|
||||
document.removeEventListener('singlepageviewer:closed', this.boundHandleSinglePageViewer);
|
||||
document.removeEventListener('singlepageviewer:pagechanged', this.boundHandleSinglePageViewer);
|
||||
// Only remove event listeners if they were attached
|
||||
if (this.eventListenersAttached) {
|
||||
document.removeEventListener('singlepageviewer:opened', this.boundHandleSinglePageViewer);
|
||||
document.removeEventListener('singlepageviewer:closed', this.boundHandleSinglePageViewer);
|
||||
document.removeEventListener('singlepageviewer:pagechanged', this.boundHandleSinglePageViewer);
|
||||
this.eventListenersAttached = false;
|
||||
}
|
||||
|
||||
this.pageContainers.clear();
|
||||
}
|
||||
|
||||
@@ -140,7 +140,6 @@ export class PlaceAccordion extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.setupAccordion();
|
||||
this.setupEventListeners();
|
||||
this.updateBorders();
|
||||
this.setupMapEventListeners();
|
||||
this.setupHoverEvents();
|
||||
}
|
||||
@@ -160,26 +159,12 @@ export class PlaceAccordion extends HTMLElement {
|
||||
}
|
||||
|
||||
setupAccordion() {
|
||||
// Add chevron icon if not already present
|
||||
if (!this.querySelector(".accordion-chevron")) {
|
||||
const chevron = document.createElement("i");
|
||||
chevron.className =
|
||||
"ri-chevron-down-line accordion-chevron transition-transform duration-200 text-slate-400";
|
||||
|
||||
// Find the badge and insert chevron before it
|
||||
const badge = this.querySelector('[class*="bg-slate-100"]');
|
||||
if (badge) {
|
||||
badge.parentNode.insertBefore(chevron, badge);
|
||||
}
|
||||
}
|
||||
|
||||
// Create content container if not exists
|
||||
if (!this.querySelector("[data-content]")) {
|
||||
const placeId = this.getAttribute("data-place-id");
|
||||
const contentContainer = document.createElement("div");
|
||||
contentContainer.setAttribute("data-content", "");
|
||||
contentContainer.className =
|
||||
"accordion-content overflow-hidden transition-all duration-300 max-h-0";
|
||||
"accordion-content overflow-hidden transition-all duration-300 max-h-0 border-b border-slate-200";
|
||||
|
||||
// Add HTMX attributes to override body defaults
|
||||
contentContainer.setAttribute("hx-get", `/ort/fragment/${placeId}`);
|
||||
@@ -272,8 +257,6 @@ export class PlaceAccordion extends HTMLElement {
|
||||
if (this.isLoading) return;
|
||||
|
||||
this.isExpanded = true;
|
||||
this.updateChevron();
|
||||
this.updateBorders();
|
||||
|
||||
const contentContainer = this.querySelector("[data-content]");
|
||||
if (!contentContainer) return;
|
||||
@@ -289,8 +272,6 @@ export class PlaceAccordion extends HTMLElement {
|
||||
|
||||
collapse() {
|
||||
this.isExpanded = false;
|
||||
this.updateChevron();
|
||||
this.updateBorders();
|
||||
|
||||
const contentContainer = this.querySelector("[data-content]");
|
||||
if (contentContainer) {
|
||||
@@ -330,33 +311,6 @@ export class PlaceAccordion extends HTMLElement {
|
||||
// Trigger the HTMX request
|
||||
htmx.trigger(contentContainer, "load-content");
|
||||
}
|
||||
|
||||
updateChevron() {
|
||||
const chevron = this.querySelector(".accordion-chevron");
|
||||
if (chevron) {
|
||||
if (this.isExpanded) {
|
||||
chevron.style.transform = "rotate(180deg)";
|
||||
} else {
|
||||
chevron.style.transform = "rotate(0deg)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateBorders() {
|
||||
if (this.isExpanded) {
|
||||
// When expanded: remove border from header, add border to whole component
|
||||
this.classList.add("border-b", "border-slate-100");
|
||||
} else {
|
||||
// When collapsed: add border to component (for separation between items)
|
||||
this.classList.add("border-b", "border-slate-100");
|
||||
}
|
||||
|
||||
// Remove border from last item if it's the last child
|
||||
const isLastChild = !this.nextElementSibling;
|
||||
if (isLastChild) {
|
||||
this.classList.remove("border-b");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,7 +479,8 @@ export class PlacesMap extends HTMLElement {
|
||||
circle.setAttribute("filter", "drop-shadow(0 0.05 0.08 rgba(0,0,0,0.15))");
|
||||
circle.style.cursor = "pointer";
|
||||
circle.style.pointerEvents = "all";
|
||||
circle.style.transition = "r 0.3s ease, fill 0.3s ease, stroke 0.3s ease, opacity 0.3s ease";
|
||||
circle.style.transition =
|
||||
"r 0.3s ease, fill 0.3s ease, stroke 0.3s ease, opacity 0.3s ease";
|
||||
|
||||
// Add hover effects for white dots
|
||||
circle.addEventListener("mouseenter", () => {
|
||||
@@ -664,7 +619,6 @@ export class PlacesMap extends HTMLElement {
|
||||
placeContainers.forEach((container) => {
|
||||
this.intersectionObserver.observe(container);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
setPointActive(circle) {
|
||||
@@ -701,7 +655,6 @@ export class PlacesMap extends HTMLElement {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (this.tooltip && tooltipText) {
|
||||
// Set tooltip content and position
|
||||
this.tooltip.textContent = tooltipText;
|
||||
|
||||
@@ -418,7 +418,7 @@ class SchnellauswahlButton extends HTMLElement {
|
||||
this.innerHTML = `
|
||||
<button
|
||||
id="filter-toggle"
|
||||
class="mr-2 text-lg border px-4 h-full hover:bg-slate-200 transition-colors cursor-pointer"
|
||||
class="mr-2 text-lg border px-4 h-full bg-white hover:bg-slate-200 transition-colors cursor-pointer"
|
||||
title="Schnellfilter öffnen/schließen">
|
||||
<i class="ri-filter-2-line"></i> <div class="inline-block text-lg">Schnellauswahl</div>
|
||||
</button>
|
||||
@@ -543,36 +543,36 @@ class NavigationMenu extends HTMLElement {
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['git-commit', 'git-date', 'git-url'];
|
||||
return ["git-commit", "git-date", "git-url"];
|
||||
}
|
||||
|
||||
get gitCommit() {
|
||||
return this.getAttribute('git-commit');
|
||||
return this.getAttribute("git-commit");
|
||||
}
|
||||
|
||||
get gitDate() {
|
||||
return this.getAttribute('git-date');
|
||||
return this.getAttribute("git-date");
|
||||
}
|
||||
|
||||
get gitUrl() {
|
||||
return this.getAttribute('git-url');
|
||||
return this.getAttribute("git-url");
|
||||
}
|
||||
|
||||
formatCommitInfo() {
|
||||
if (!this.gitCommit) {
|
||||
return 'Keine Commit-Info';
|
||||
return "Keine Commit-Info";
|
||||
}
|
||||
|
||||
const shortCommit = this.gitCommit.substring(0, 7);
|
||||
|
||||
if (this.gitDate) {
|
||||
const date = new Date(this.gitDate);
|
||||
const formattedDate = date.toLocaleDateString('de-DE', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
const formattedDate = date.toLocaleDateString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
return `${shortCommit} (${formattedDate})`;
|
||||
return `${shortCommit} - ${formattedDate}`;
|
||||
}
|
||||
|
||||
return shortCommit;
|
||||
@@ -590,35 +590,35 @@ class NavigationMenu extends HTMLElement {
|
||||
|
||||
createMenu() {
|
||||
this.innerHTML = `
|
||||
<div>
|
||||
<div class="h-full relative">
|
||||
<button
|
||||
class="ml-2 text-2xl border px-4 h-full hover:bg-slate-200 transition-colors cursor-pointer"
|
||||
class="ml-2 text-2xl border px-4 h-full bg-white hover:bg-slate-200 transition-colors cursor-pointer"
|
||||
id="menu-toggle">
|
||||
<i class="ri-menu-line"></i>
|
||||
</button>
|
||||
<div id="menu-dropdown" class="hidden absolute bg-slate-50 px-5 py-3 z-50">
|
||||
<div>
|
||||
<div>Übersicht nach</div>
|
||||
<div class="ml-2 flex flex-col gap-y-2 mt-2">
|
||||
<div id="menu-dropdown" class="hidden absolute bg-white py-2 z-50 top-[115%] right-0 shadow-sm">
|
||||
<div class="px-5">
|
||||
<div class="whitespace-nowrap">Übersicht nach</div>
|
||||
<div class="ml-2 flex flex-col gap-y-2 mt-2 whitespace-nowrap">
|
||||
<a href="/">Jahrgängen</a>
|
||||
<a href="/akteure/a">Personen & Werke</a>
|
||||
<a href="/akteure/a">Personen & Werken</a>
|
||||
<a href="/kategorie/">Betragsarten</a>
|
||||
<a href="/ort/">Orten</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-slate-300 pt-2 mt-2">
|
||||
<div class="border-t border-slate-300 pt-2 mt-2 px-5">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<a href="/edition/">Geschichte & Edition der KGPZ</a>
|
||||
<a href="/zitation/">Zitation</a>
|
||||
<a href="/kontakt/">Kontakt</a>
|
||||
</div>
|
||||
<div class="mt-3 pt-2 border-t border-slate-200 text-xs text-slate-600">
|
||||
<a href="${this.gitUrl || 'https://github.com/Theodor-Springmann-Stiftung/KGPZ.git'}" target="_blank" class="flex items-center gap-1 hover:text-slate-800">
|
||||
<i class="ri-git-branch-line"></i>
|
||||
<span>${this.formatCommitInfo()}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 pt-2 border-t border-slate-200 text-xs text-slate-600 px-2 text-centeer vertical-align-middle">
|
||||
<i class="ri-git-branch-line"></i>
|
||||
<a href="${this.gitUrl || "https://github.com/Theodor-Springmann-Stiftung/KGPZ.git"}" target="_blank" class="hover:text-slate-800">
|
||||
<span>Commit ${this.formatCommitInfo()}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -721,23 +721,36 @@ customElements.define("navigation-menu", NavigationMenu);
|
||||
|
||||
/**
|
||||
* Global event handler for quickfilter selections
|
||||
* Dispatches custom events when users select persons or places from quickfilter
|
||||
* Dispatches custom events when users select persons, places, or categories from quickfilter
|
||||
*/
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Add event delegation for person and place links in quickfilter
|
||||
// Add event delegation for person, place, and category links in quickfilter
|
||||
document.addEventListener("click", function (event) {
|
||||
// Check if the clicked element is a person or place link within the quickfilter
|
||||
const quickfilterTarget = event.target.closest('a[href^="/akteure/"], a[href^="/ort/"]');
|
||||
// Check if the clicked element is a person, place, or category link within the quickfilter
|
||||
const quickfilterTarget = event.target.closest(
|
||||
'a[href^="/akteure/"], a[href^="/ort/"], a[href^="/kategorie/"]',
|
||||
);
|
||||
const filterContainer = document.getElementById("filter-container");
|
||||
|
||||
if (quickfilterTarget && filterContainer && filterContainer.contains(quickfilterTarget)) {
|
||||
// Determine the type based on the URL
|
||||
let type;
|
||||
const href = quickfilterTarget.getAttribute("href");
|
||||
if (href.startsWith("/akteure/")) {
|
||||
type = "person";
|
||||
} else if (href.startsWith("/ort/")) {
|
||||
type = "place";
|
||||
} else if (href.startsWith("/kategorie/")) {
|
||||
type = "category";
|
||||
}
|
||||
|
||||
// Dispatch custom event to notify components
|
||||
const selectionEvent = new CustomEvent("quickfilter:selection", {
|
||||
detail: {
|
||||
type: quickfilterTarget.getAttribute("href").startsWith("/akteure/") ? "person" : "place",
|
||||
type: type,
|
||||
source: "quickfilter",
|
||||
id: quickfilterTarget.getAttribute("href").split("/").pop(),
|
||||
url: quickfilterTarget.getAttribute("href"),
|
||||
id: href.split("/").pop(),
|
||||
url: href,
|
||||
},
|
||||
bubbles: true,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user