This commit is contained in:
2026-07-18 15:00:54 +02:00
parent db62cee09b
commit 39d90c9fe0
2 changed files with 27 additions and 246 deletions
+13 -41
View File
@@ -2,16 +2,8 @@
if (session_status() === PHP_SESSION_NONE) { if (session_status() === PHP_SESSION_NONE) {
session_start(); session_start();
} }
$log_msg = "DEBUG search-results.php: search_results count = " . count($_SESSION["search_results"] ?? []) . ", query = " . ($_SESSION["search_query"] ?? "LEER");
echo "<script>console.log(" . json_encode($log_msg) . ");</script>";
$all_results = $_SESSION["search_results"] ?? []; $all_results = $_SESSION["search_results"] ?? [];
?>
<!-- Übergabe der rohen PHP-Ergebnisse an JavaScript -->
<script id="search-data-json" type="application/json">
<?php echo json_encode($all_results); ?>
</script>
<?php
$query = $_SESSION["search_query"] ?? ""; $query = $_SESSION["search_query"] ?? "";
$totalResultsCount = count($all_results); $totalResultsCount = count($all_results);
@@ -53,9 +45,9 @@ $resultCount = count($results);
<!-- Links: Seitenleiste für Filter und Suche --> <!-- Links: Seitenleiste für Filter und Suche -->
<aside class="s-res-sidebar"> <aside class="s-res-sidebar">
<!-- Sortierfuntion Box und Such Box--> <!-- Sortierfuntion Box und Such Box-->
<form action="php/controller/search-results-controller.php" method="GET" id="search-form-id" class="s-res-sidebar-form"> <form action="php/controller/search-results-controller.php" method="GET" id="search-form-id" class="s-res-sidebar-form">
<input type="hidden" id="s-res-page-input" name="page" value="<?php echo $_GET['page'] ?? 1; ?>"> <input type="hidden" id="s-res-page-input" name="page" value="<?php echo $_GET['page'] ?? 1; ?>">
<div class="s-res-sidebar-box"> <div class="s-res-sidebar-box">
@@ -133,13 +125,13 @@ $resultCount = count($results);
<!-- Ergebnisliste --> <!-- Ergebnisliste -->
<div class="s-res-list"> <div class="s-res-list">
<?php <?php
if (!empty($results)): ?> if (!empty($results)): ?>
<?php foreach ($results as $item): <?php foreach ($results as $item):
// Anzahl der Likes ermitteln (falls es ein Array ist, zählen; falls Zahl, direkt nutzen) // Anzahl der Likes ermitteln (falls es ein Array ist, zählen; falls Zahl, direkt nutzen)
$likesCount = isset($item['likes']) && is_array($item['likes']) ? count($item['likes']) : ($item['likes'] ?? 0); $likesCount = isset($item['likes']) && is_array($item['likes']) ? count($item['likes']) : ($item['likes'] ?? 0);
?> ?>
<div class="s-res-item" data-likes="<?php echo $likesCount; ?>" data-category="<?php echo strtolower($item['category'] ?? ''); ?>"> <div class="s-res-item" data-likes="<?php echo $likesCount; ?>" data-category="<?php echo strtolower($item['category'] ?? ''); ?>">
<div class="s-res-content"> <div class="s-res-content">
<h2 class="s-res-item-title"> <h2 class="s-res-item-title">
@@ -159,13 +151,13 @@ $resultCount = count($results);
</div> </div>
<?php endforeach; ?> <?php endforeach; ?>
<?php <?php
elseif (isset($_SESSION["search_query"]) && $_SESSION["search_query"] !== "" && $resultCount === 0): ?> elseif (isset($_SESSION["search_query"]) && $_SESSION["search_query"] !== "" && $resultCount === 0): ?>
<p>Keine Beiträge zu diesem Suchbegriff gefunden.</p> <p>Keine Beiträge zu diesem Suchbegriff gefunden.</p>
<?php <?php
elseif (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_search_query"): ?> elseif (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_search_query"): ?>
<p>Unzulässige Suchanfrage</p> <p>Unzulässige Suchanfrage</p>
<?php endif; ?> <?php endif; ?>
<?php <?php
unset($_SESSION["message"]); unset($_SESSION["message"]);
@@ -186,33 +178,13 @@ $resultCount = count($results);
</div> </div>
<div class="s-res-page-navigation"> <div class="s-res-page-navigation">
<!-- Vorherige Seite Link --> <button type="button" class="s-res-page-btn" id="prev-page-btn" data-page="0">«</button>
<?php if ($currentPage > 1): ?>
<a href="?page=<?php echo $currentPage - 1; ?>&limit=<?php echo $limit; ?>" class="s-res-page-btn" id="prev-page-btn" data-page="<?php echo $currentPage - 1; ?>">«</a>
<?php else: ?>
<span class="s-res-page-btn disabled">«</span>
<?php endif; ?>
<!-- Fallback-Seitenzahlen für Nutzer OHNE JavaScript --> <span id="dynamic-page-numbers"></span>
<span id="dynamic-page-numbers">
<noscript>
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
<a href="?page=<?php echo $i; ?>&limit=<?php echo $limit; ?>" class="s-res-page-btn <?php echo $i === $currentPage ? 'active' : ''; ?>">
<?php echo $i; ?>
</a>
<?php endfor; ?>
</noscript>
</span>
<!-- Nächste Seite Link --> <button type="button" class="s-res-page-btn" id="next-page-btn" data-page="2">»</button>
<?php if ($currentPage < $totalPages): ?>
<a href="?page=<?php echo $currentPage + 1; ?>&limit=<?php echo $limit; ?>" class="s-res-page-btn" id="next-page-btn" data-page="<?php echo $currentPage + 1; ?>">»</a>
<?php else: ?>
<span class="s-res-page-btn disabled">»</span>
<?php endif; ?>
</div> </div>
</div> </div>
</main> </main>
+14 -205
View File
@@ -1,218 +1,27 @@
// Globale Variablen für den JavaScript-Betrieb
let allItems = [];
let filteredItems = [];
let currentJsPage = 1;
let jsLimit = 10;
function initPaginator() { function initPaginator() {
const dataContainer = document.getElementById('search-data-json'); const form = document.getElementById('search-form-id');
if (!dataContainer) return; const pageInput = document.getElementById('s-res-page-input');
const pageButtons = document.querySelectorAll('.s-res-page-navigation .s-res-page-btn');
// 1. Daten aus PHP-JSON-Schnittstelle laden pageButtons.forEach(button => {
try { button.addEventListener('click', function() {
allItems = JSON.parse(dataContainer.textContent); if (this.disabled) return;
} catch (e) {
console.error("Fehler beim Laden der Suchdaten:", e);
return;
}
// 2. Event-Listener für Live-Interaktionen im Browser registrieren const targetPage = this.getAttribute('data-page');
const sortRadios = document.querySelectorAll('.sort-radio');
const categorySelect = document.getElementById('category-filter');
const limitSelect = document.getElementById('s-res-per-page');
sortRadios.forEach(radio => radio.addEventListener('change', applyFiltersAndRender)); if (targetPage && form && pageInput) {
if (categorySelect) categorySelect.addEventListener('change', applyFiltersAndRender); pageInput.value = targetPage;
if (limitSelect) { form.submit();
limitSelect.addEventListener('change', function() {
jsLimit = parseInt(this.value) || 10;
currentJsPage = 1; // Zurück auf Seite 1 bei Limit-Wechsel
applyFiltersAndRender();
});
}
// Pfeil-Navigation (Vor / Zurück) abfangen
const prevBtn = document.getElementById('prev-page-btn');
const nextBtn = document.getElementById('next-page-btn');
if (prevBtn) {
prevBtn.addEventListener('click', function(e) {
e.preventDefault();
if (currentJsPage > 1) {
currentJsPage--;
renderListAndPagination();
} }
}); });
}
if (nextBtn) {
nextBtn.addEventListener('click', function(e) {
e.preventDefault();
const totalPages = Math.max(1, Math.ceil(filteredItems.length / jsLimit));
if (currentJsPage < totalPages) {
currentJsPage++;
renderListAndPagination();
}
});
}
// Initialer Start: Daten verarbeiten und anzeigen
// Liest das vom Server übergebene Limit aus
if (limitSelect) jsLimit = parseInt(limitSelect.value) || 10;
applyFiltersAndRender();
}
// Verarbeitet Sortierung + Filterung komplett im Browser (Serverentlastung)
function applyFiltersAndRender() {
// KATEGORIE FILTERN
const categorySelect = document.getElementById('category-filter');
const activeCategory = categorySelect ? categorySelect.value : 'all';
if (activeCategory === 'all') {
filteredItems = [...allItems];
} else {
filteredItems = allItems.filter(item =>
item.category && item.category.toLowerCase() === activeCategory.toLowerCase()
);
}
// SORTIERUNG ANWENDEN
const activeSortRadio = document.querySelector('.sort-radio:checked');
const sortStyle = activeSortRadio ? activeSortRadio.value : 'alphabet';
if (sortStyle === 'alphabet') {
filteredItems.sort((a, b) => (a.title || '').localeCompare(b.title || '', 'de', { sensitivity: 'base' }));
} else if (sortStyle === 'likes') {
filteredItems.sort((a, b) => {
const countA = Array.isArray(a.likes) ? a.likes.length : (parseInt(a.likes) || 0);
const countB = Array.isArray(b.likes) ? b.likes.length : (parseInt(b.likes) || 0);
return countB - countA;
});
} else if (sortStyle === 'newest') {
filteredItems.sort((a, b) => (b.creationDate || '').localeCompare(a.creationDate || ''));
} else if (sortStyle === 'oldest') {
filteredItems.sort((a, b) => (a.creationDate || '').localeCompare(b.creationDate || ''));
}
// Nach dem Filtern/Sortieren springen wir zurück auf Seite 1
currentJsPage = 1;
renderListAndPagination();
}
// HTML-Listenansicht und Paginierungs-Zahlen neu aufbauen
function renderListAndPagination() {
const listContainer = document.querySelector('.s-res-list');
const pageNumbersContainer = document.getElementById('dynamic-page-numbers');
if (!listContainer) return;
// Gesamtseitenzahl berechnen
const totalPages = Math.max(1, Math.ceil(filteredItems.length / jsLimit));
if (currentJsPage > totalPages) currentJsPage = totalPages;
// Meta-Text aktualisieren (Trefferanzeige)
const metaText = document.querySelector('.s-res-meta');
if (metaText) {
const queryText = metaText.textContent.split('"')[1] || '';
metaText.innerHTML = `${filteredItems.length} Treffer für Ihre Suchanfrage "${queryText}"`;
}
// 1. ERGEBNISLISTE IM DOM REINJECKTEN
listContainer.innerHTML = ''; // Vorherige Ergebnisse leeren
if (filteredItems.length === 0) {
listContainer.innerHTML = '<p>Keine Beiträge zu diesem Suchbegriff gefunden.</p>';
if (pageNumbersContainer) pageNumbersContainer.innerHTML = '';
updateArrowButtons(totalPages);
return;
}
// Ausschnitt für die aktuelle Seite berechnen (Offset)
const offset = (currentJsPage - 1) * jsLimit;
const pageItems = filteredItems.slice(offset, offset + jsLimit);
// HTML für die Zeilen generieren
pageItems.forEach(item => {
const likesCount = Array.isArray(item.likes) ? item.likes.length : (parseInt(item.likes) || 0);
const itemHtml = `
<div class="s-res-item" data-likes="${likesCount}" data-category="${(item.category || '').toLowerCase()}">
<div class="s-res-content">
<h2 class="s-res-item-title">
<a href="index.php?pfad=showArticle&id=${item.id}" class="s-res-link">${escapeHtml(item.title)}</a>
</h2>
<div class="s-res-meta-row">
<p class="s-res-author">Von: <span class="s-res-author-name">${escapeHtml(item.author)}</span></p>
<span class="s-res-likes">❤️ ${likesCount}</span>
</div>
</div>
<div class="s-res-arrow">&rarr;</div>
</div>
`;
listContainer.insertAdjacentHTML('beforeend', itemHtml);
}); });
// 2. DYNAMISCHE SEITENZAHLEN GENERIEREN
if (pageNumbersContainer) {
pageNumbersContainer.innerHTML = ''; // Vorherige Zahlen leeren
// Erzeugt Klickbare Seitenzahlen im JS-Modus
for (let i = 1; i <= totalPages; i++) {
const pageBtn = document.createElement('button');
pageBtn.type = 'button';
pageBtn.className = `s-res-page-btn ${i === currentJsPage ? 'active' : ''}`;
pageBtn.innerText = i;
pageBtn.addEventListener('click', function() {
currentJsPage = i;
renderListAndPagination();
});
pageNumbersContainer.appendChild(pageBtn);
}
}
updateArrowButtons(totalPages);
} }
// Steuert die Aktivierung/Deaktivierung der Vor- und Zurück-Pfeile // ist das DOM bereits vollständig aufgebaut?
function updateArrowButtons(totalPages) {
const prevBtn = document.getElementById('prev-page-btn');
const nextBtn = document.getElementById('next-page-btn');
if (prevBtn) {
if (currentJsPage <= 1) {
prevBtn.classList.add('disabled');
prevBtn.style.pointerEvents = 'none';
} else {
prevBtn.classList.remove('disabled');
prevBtn.style.pointerEvents = 'auto';
}
}
if (nextBtn) {
if (currentJsPage >= totalPages) {
nextBtn.classList.add('disabled');
nextBtn.style.pointerEvents = 'none';
} else {
nextBtn.classList.remove('disabled');
nextBtn.style.pointerEvents = 'auto';
}
}
}
// Hilfsfunktion gegen XSS-Injections im Browser
function escapeHtml(text) {
if (!text) return '';
return text.toString()
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// DOM-Ready Check
if (document.readyState === 'loading') { if (document.readyState === 'loading') {
// Falls noch geladen wird, auf das Event warten
document.addEventListener('DOMContentLoaded', initPaginator); document.addEventListener('DOMContentLoaded', initPaginator);
} else { } else {
// Falls das HTML bereits komplett da ist, sofort ausführen
initPaginator(); initPaginator();
} }