mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-29 17:15:31 +00:00
Fixed some search things
This commit is contained in:
@@ -21,9 +21,27 @@ import {
|
||||
initializeNewspaperLayout,
|
||||
} from "./issue.js";
|
||||
|
||||
|
||||
// Update citation links to highlight current page references
|
||||
function updateCitationLinks() {
|
||||
const currentPath = window.location.pathname;
|
||||
|
||||
// Don't disable citation links on search pages - they should all remain clickable
|
||||
// Check both URL path and if search results are currently displayed in DOM
|
||||
const hasSearchResults = document.querySelector('main .grid.grid-cols-1.lg\\:grid-cols-3') !== null; // Search results layout
|
||||
const hasSearchHeaders = document.querySelector('main h3 u') !== null; // Underlined section headers (Werke, Beiträge, etc.)
|
||||
const isSearchPage = currentPath.includes('/search') || currentPath.includes('/suche') || hasSearchResults || hasSearchHeaders;
|
||||
|
||||
if (isSearchPage) {
|
||||
const citationLinks = document.querySelectorAll(".citation-link[data-citation-url]");
|
||||
citationLinks.forEach((link) => {
|
||||
// Reset to default styling on search pages
|
||||
link.classList.remove("text-red-700", "pointer-events-none");
|
||||
link.removeAttribute("aria-current");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const citationLinks = document.querySelectorAll(".citation-link[data-citation-url]");
|
||||
|
||||
citationLinks.forEach((link) => {
|
||||
@@ -128,6 +146,7 @@ let htmxAfterSwapHandler = function (event) {
|
||||
// Update citation links after navigation
|
||||
updateCitationLinks();
|
||||
|
||||
|
||||
// Execute all queued functions
|
||||
ExecuteSettleQueue();
|
||||
|
||||
|
||||
@@ -759,3 +759,154 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* SearchBar - Web component for the main search functionality
|
||||
* Encapsulates search input, loading indicator, reset button, and all related behavior
|
||||
*/
|
||||
class SearchBar extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.htmxRequestListeners = [];
|
||||
this.htmxAfterSwapListener = null;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.createSearchBar();
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
// Clean up all event listeners
|
||||
this.cleanup();
|
||||
}
|
||||
|
||||
createSearchBar() {
|
||||
this.innerHTML = `
|
||||
<div class="relative">
|
||||
<input
|
||||
type="search"
|
||||
name="q"
|
||||
id="search"
|
||||
placeholder="Suche"
|
||||
autocomplete="off"
|
||||
class="px-2.5 py-1.5 border w-full bg-white pr-10"
|
||||
hx-get="/suche/?noCache=true"
|
||||
hx-trigger="input changed delay:200ms, keyup[key=='Enter']"
|
||||
hx-select="main"
|
||||
hx-target="main"
|
||||
hx-indicator="#search-loading" />
|
||||
<div
|
||||
id="search-loading"
|
||||
class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 p-1 htmx-indicator">
|
||||
<i class="ri-loader-4-line text-lg animate-spin"></i>
|
||||
</div>
|
||||
<button
|
||||
id="search-reset"
|
||||
type="button"
|
||||
class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors p-1 cursor-pointer hidden hover:bg-gray-100 rounded"
|
||||
title="Suche schließen">
|
||||
<i class="ri-close-line text-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
const searchInput = this.querySelector('#search');
|
||||
const resetButton = this.querySelector('#search-reset');
|
||||
const loadingIndicator = this.querySelector('#search-loading');
|
||||
|
||||
if (!searchInput || !resetButton) return;
|
||||
|
||||
// Store the current URL to detect changes
|
||||
this.currentURL = window.location.pathname;
|
||||
|
||||
// Function to toggle reset button visibility
|
||||
const toggleResetButton = () => {
|
||||
if (searchInput.value.trim() !== '') {
|
||||
resetButton.classList.remove('hidden');
|
||||
} else {
|
||||
resetButton.classList.add('hidden');
|
||||
}
|
||||
};
|
||||
|
||||
// Check initial state (in case of page refresh with existing search)
|
||||
toggleResetButton();
|
||||
|
||||
// Show/hide reset button as user types
|
||||
searchInput.addEventListener('input', toggleResetButton);
|
||||
|
||||
// Handle reset button click
|
||||
resetButton.addEventListener('click', () => {
|
||||
searchInput.value = '';
|
||||
resetButton.classList.add('hidden');
|
||||
|
||||
// Trigger the same HTMX behavior that happens when manually clearing the field
|
||||
// This will automatically navigate back to the previous page
|
||||
searchInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
|
||||
// Focus back on search input
|
||||
searchInput.focus();
|
||||
});
|
||||
|
||||
// Handle HTMX request lifecycle - hide reset button during loading
|
||||
if (loadingIndicator) {
|
||||
// Hide reset button when loading starts
|
||||
const beforeRequestHandler = (event) => {
|
||||
if (event.detail.elt === searchInput) {
|
||||
resetButton.style.display = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
// Show reset button when loading ends (if there's still text)
|
||||
const afterRequestHandler = (event) => {
|
||||
if (event.detail.elt === searchInput) {
|
||||
resetButton.style.display = '';
|
||||
toggleResetButton();
|
||||
}
|
||||
};
|
||||
|
||||
document.body.addEventListener('htmx:beforeRequest', beforeRequestHandler);
|
||||
document.body.addEventListener('htmx:afterRequest', afterRequestHandler);
|
||||
|
||||
// Store references for cleanup
|
||||
this.htmxRequestListeners.push(
|
||||
{ event: 'htmx:beforeRequest', handler: beforeRequestHandler },
|
||||
{ event: 'htmx:afterRequest', handler: afterRequestHandler }
|
||||
);
|
||||
}
|
||||
|
||||
// Simple click listener to clear search when any link is clicked
|
||||
this.linkClickHandler = (event) => {
|
||||
const clickedElement = event.target;
|
||||
const link = clickedElement.closest('a[href]');
|
||||
|
||||
// If a link was clicked and it has an href, clear the search
|
||||
if (link && link.getAttribute('href') && searchInput.value.trim() !== '') {
|
||||
searchInput.value = '';
|
||||
resetButton.classList.add('hidden');
|
||||
}
|
||||
};
|
||||
|
||||
// Listen for clicks on the entire document
|
||||
document.addEventListener('click', this.linkClickHandler);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
// Remove HTMX request listeners
|
||||
this.htmxRequestListeners.forEach(({ event, handler }) => {
|
||||
document.body.removeEventListener(event, handler);
|
||||
});
|
||||
this.htmxRequestListeners = [];
|
||||
|
||||
// Remove link click listener
|
||||
if (this.linkClickHandler) {
|
||||
document.removeEventListener('click', this.linkClickHandler);
|
||||
this.linkClickHandler = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register the custom element
|
||||
customElements.define("search-bar", SearchBar);
|
||||
|
||||
Reference in New Issue
Block a user