search-results.js

This commit is contained in:
2026-07-18 15:05:22 +02:00
parent 39d90c9fe0
commit 986b85bed9
5 changed files with 554 additions and 128 deletions
+121 -80
View File
@@ -4,18 +4,48 @@ if (session_status() === PHP_SESSION_NONE) {
}
$all_results = $_SESSION["search_results"] ?? [];
$query = $_SESSION["search_query"] ?? "";
$totalResultsCount = count($all_results);
$query = $_SESSION["search_query"] ?? "";
// ---------------------------------------------------------------
// Parameter aus der URL lesen & validieren
// ---------------------------------------------------------------
$allowedCategories = [
'all', 'Deutsch', 'Englisch', 'Franzoesisch', 'Latein', 'Literatur',
'Mathematik', 'Biologie', 'Informatik', 'Chemie', 'Physik', 'Astronomie',
'Geschichte', 'Erdkunde', 'Sozialkunde', 'Wirtschaftskunde', 'Religion',
'Ethikunterricht', 'Philosophie', 'Psychologie', 'Kunst', 'Musik',
'Theater', 'Technik', 'Werken', 'Hauswirtschaft', 'Sport',
];
$category = $_GET['category'] ?? 'all';
if (!in_array($category, $allowedCategories, true)) {
$category = 'all';
}
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
if (!in_array($limit, [10, 20, 50, 100])) {
if (!in_array($limit, [10, 20, 50, 100], true)) {
$limit = 10;
}
// Gesamtseitenzahl
$totalPages = max(1, ceil($totalResultsCount / $limit));
$currentSort = $_SESSION['search_sort'] ?? 'alphabet';
// ---------------------------------------------------------------
// Diese Berechnung ist der Server-seitige Fallback für Nutzer ohne
// JavaScript. Sobald JS aktiv ist, übernimmt js/search-results.js
// Filterung, Sortierung und Pagination komplett im Browser (auf
// Basis des unten eingebetteten JSON-Datensatzes) und überschreibt
// diese Ausgabe live, ohne dass eine neue Seite geladen wird.
// ---------------------------------------------------------------
$filteredResults = $all_results;
if ($category !== 'all') {
$filteredResults = array_values(array_filter($filteredResults, function ($item) use ($category) {
return ($item['category'] ?? '') === $category;
}));
}
$totalResultsCount = count($filteredResults);
$totalPages = max(1, (int)ceil($totalResultsCount / $limit));
// Aktuelle Seite auslesen und validieren
$currentPage = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if ($currentPage < 1) {
$currentPage = 1;
@@ -23,42 +53,68 @@ if ($currentPage < 1) {
$currentPage = $totalPages;
}
// Startpunkt im Array berechnen (Offset)
$offset = ($currentPage - 1) * $limit;
// Nur die Ergebnisse für die aktuelle Seite ausschneiden
//$results = array_slice($all_results, $offset, $limit);
$results = $all_results;
$offset = ($currentPage - 1) * $limit;
$results = array_slice($filteredResults, $offset, $limit);
$resultCount = count($results);
// Hilfsfunktion, um Pagination-Links zu bauen, die alle aktuellen
// Parameter (q, sort, limit, category) beibehalten.
function buildPageUrl(int $page, string $query, string $sort, int $limit, string $category): string
{
$params = [
'pfad' => 'search-results',
'q' => $query,
'sort' => $sort,
'limit' => $limit,
'category' => $category,
'page' => $page,
];
return 'index.php?' . http_build_query($params);
}
// ---------------------------------------------------------------
// JSON-Datensatz für die clientseitige Aufbereitung (Filter,
// Sortierung, Pagination) durch js/search-results.js. Enthält ALLE
// Treffer der Suche (unabhängig von Kategorie/Sortierung/Seite),
// damit im Browser ohne weitere Serveranfragen gearbeitet werden kann.
// ---------------------------------------------------------------
$jsonItems = array_map(function ($item) {
$likes = isset($item['likes']) && is_array($item['likes']) ? count($item['likes']) : ($item['likes'] ?? 0);
return [
'id' => $item['id'] ?? null,
'title' => $item['title'] ?? '',
'author' => $item['author'] ?? '',
'category' => $item['category'] ?? '',
'likes' => $likes,
'creationDate'=> $item['creationDate'] ?? '',
];
}, $all_results);
?>
<noscript>
Bitte JavaScript aktivieren!
Bitte JavaScript aktivieren, um die volle Funktionalität (Live-Filterung ohne Neuladen) zu nutzen. Die Seite funktioniert auch ohne JavaScript Sortierung, Filterung und Seitenwechsel erfolgen dann über die Formular- bzw. Link-Auswahl.
</noscript>
<!--
Seite: Suchergebnisse
Inhalt: Zeigt die Ergebnisse einer Suche an
Seite: Suchergebnisse
Inhalt: Zeigt die Ergebnisse einer Suche an
-->
<div class="s-res-layout-grid">
<?php include_once "includes/alertMessages.php"?>
<?php include_once "includes/alertMessages.php" ?>
<!-- Links: Seitenleiste für Filter und Suche -->
<aside class="s-res-sidebar">
<!-- Sortierfuntion Box und Such Box -->
<form action="php/controller/search-results-controller.php" method="GET" id="searchform-id" class="s-res-sidebar-form">
<!-- Sortierfuntion Box und Such Box-->
<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 (int)$currentPage; ?>">
<div class="s-res-sidebar-box">
<h3 class="s-res-sidebar-title">Suche anpassen</h3>
<input type="search" id="site-search" name="q" placeholder="Suchen..." class="nav__search" value="<?php echo htmlspecialchars($query); ?>" maxlength="50" required>
<input type="search" id="site-search" name="q" placeholder="Suchen..."
class="nav__search" value="<?php echo htmlspecialchars($query); ?>" maxlength="50" required>
<button type="submit" class="nav__search-button">Suchen</button>
</div>
<div class="s-res-sidebar-box">
<h3 class="s-res-sidebar-title">Sortierung</h3>
<?php $currentSort = $_SESSION['search_sort'] ?? 'alphabet'; ?>
<div class="s-res-filter-group">
<label class="s-res-filter-option">
<input type="radio" name="sort" value="alphabet" class="sort-radio" <?php echo $currentSort === 'alphabet' ? 'checked' : ''; ?>>
@@ -81,55 +137,36 @@ $resultCount = count($results);
<div class="s-res-sidebar-box">
<h3 class="s-res-sidebar-title">Kategorie filtern</h3>
<select id="category-filter" class="s-res-limit-select" style="width: 100%; padding: 8px; border-radius: 6px; border: 1px solid #cbd5e1;">
<option value="all">Alle Kategorien</option>
<option value="Deutsch">Deutsch</option>
<option value="Englisch">Englisch</option>
<option value="Franzoesisch">Französisch</option>
<option value="Latein">Latein</option>
<option value="Literatur">Literatur</option>
<option value="Mathematik">Mathematik</option>
<option value="Biologie">Biologie</option>
<option value="Informatik">Informatik</option>
<option value="Chemie">Chemie</option>
<option value="Physik">Physik</option>
<option value="Astronomie">Astronomie</option>
<option value="Geschichte">Geschichte</option>
<option value="Erdkunde">Erdkunde</option>
<option value="Sozialkunde">Sozialkunde</option>
<option value="Wirtschaftskunde">Wirtschaftskunde</option>
<option value="Religion">Religion</option>
<option value="Ethikunterricht">Ethikunterricht</option>
<option value="Philosophie">Philosophie</option>
<option value="Psychologie">Psychologie</option>
<option value="Kunst">Kunst</option>
<option value="Musik">Musik</option>
<option value="Theater">Theater</option>
<option value="Technik">Technik</option>
<option value="Werken">Werken</option>
<option value="Hauswirtschaft">Hauswirtschaft</option>
<option value="Sport">Sport</option>
<select id="category-filter" name="category" class="s-res-limit-select" style="width: 100%; padding: 8px; border-radius: 6px; border: 1px solid #cbd5e1;">
<?php foreach ($allowedCategories as $catValue):
$label = $catValue === 'all' ? 'Alle Kategorien' : ($catValue === 'Franzoesisch' ? 'Französisch' : $catValue);
?>
<option value="<?php echo htmlspecialchars($catValue); ?>" <?php echo $category === $catValue ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($label); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<!-- Für Nutzer ohne JavaScript: expliziter Button, um Sortierung/Kategorie anzuwenden -->
<noscript>
<button type="submit" class="nav__search-button">Filter anwenden</button>
</noscript>
</form>
</aside>
<main class="s-res-main-content">
<div class="s-res-header">
<h1 class="s-res-main-title">Suchergebnisse</h1>
<p class="s-res-meta"><?php echo $totalResultsCount; ?> Treffer für Ihre Suchanfrage "<?php echo htmlspecialchars($query); ?>"</p>
<p class="s-res-meta" data-query="<?php echo htmlspecialchars($query); ?>">
<?php echo $totalResultsCount; ?> Treffer für Ihre Suchanfrage "<?php echo htmlspecialchars($query); ?>"
</p>
</div>
<!-- Ergebnisliste -->
<!-- Ergebnisliste: serverseitig gerendert (No-JS-Fallback). Wird bei aktivem JS durch js/search-results.js live ersetzt. -->
<div class="s-res-list">
<?php
if (!empty($results)): ?>
<?php if (!empty($results)): ?>
<?php foreach ($results as $item):
// 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);
?>
<div class="s-res-item" data-likes="<?php echo $likesCount; ?>" data-category="<?php echo strtolower($item['category'] ?? ''); ?>">
@@ -141,35 +178,25 @@ $resultCount = count($results);
</h2>
<div class="s-res-meta-row">
<p class="s-res-author">Von: <span class="s-res-author-name"><?php echo htmlspecialchars($item['author']); ?></span></p>
<span class="s-res-likes">
❤️ <?php echo $likesCount; ?>
</span>
<span class="s-res-likes"><?php echo $likesCount; ?></span>
</div>
</div>
<div class="s-res-arrow">&rarr;</div>
</div>
<?php endforeach; ?>
<?php
elseif (isset($_SESSION["search_query"]) && $_SESSION["search_query"] !== "" && $resultCount === 0): ?>
<?php elseif (isset($_SESSION["search_query"]) && $_SESSION["search_query"] !== "" && $resultCount === 0): ?>
<p>Keine Beiträge zu diesem Suchbegriff gefunden.</p>
<?php
elseif (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_search_query"): ?>
<?php elseif (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_search_query"): ?>
<p>Unzulässige Suchanfrage</p>
<?php endif; ?>
<?php
unset($_SESSION["message"]);
?>
<?php unset($_SESSION["message"]); ?>
</div>
<div class="s-res-pagination-footer">
<div class="s-res-pagination-footer">
<!-- Auswahl der Ergebnisse pro Seite -->
<div class="s-res-limit-selector">
<label for="s-res-per-page" class="s-res-limit-label">Ergebnisse pro Seite:</label>
<select id="s-res-per-page" name="limit" class="s-res-limit-select">
<select id="s-res-per-page" name="limit" form="searchform-id" class="s-res-limit-select">
<option value="10" <?php echo $limit === 10 ? 'selected' : ''; ?>>10</option>
<option value="20" <?php echo $limit === 20 ? 'selected' : ''; ?>>20</option>
<option value="50" <?php echo $limit === 50 ? 'selected' : ''; ?>>50</option>
@@ -177,15 +204,29 @@ $resultCount = count($results);
</select>
</div>
<!-- No-JS-Fallback: echte Links, die serverseitig neu paginieren -->
<div class="s-res-page-navigation">
<button type="button" class="s-res-page-btn" id="prev-page-btn" data-page="0">«</button>
<?php if ($currentPage > 1): ?>
<a class="s-res-page-btn" href="<?php echo htmlspecialchars(buildPageUrl($currentPage - 1, $query, $currentSort, $limit, $category)); ?>">&laquo;</a>
<?php else: ?>
<span class="s-res-page-btn" aria-disabled="true">&laquo;</span>
<?php endif; ?>
<span id="dynamic-page-numbers"></span>
<span id="dynamic-page-numbers">Seite <?php echo $currentPage; ?> von <?php echo $totalPages; ?></span>
<button type="button" class="s-res-page-btn" id="next-page-btn" data-page="2">»</button>
<?php if ($currentPage < $totalPages): ?>
<a class="s-res-page-btn" href="<?php echo htmlspecialchars(buildPageUrl($currentPage + 1, $query, $currentSort, $limit, $category)); ?>">&raquo;</a>
<?php else: ?>
<span class="s-res-page-btn" aria-disabled="true">&raquo;</span>
<?php endif; ?>
</div>
</div>
</main>
</div>
<!-- Vollständiger, ungefilterter Ergebnis-Datensatz für die clientseitige
Filterung/Sortierung/Pagination (siehe js/search-results.js).
JSON_HEX_* verhindert das Ausbrechen aus dem <script>-Tag bzw. XSS. -->
<script type="application/json" id="s-res-data">
<?php echo json_encode($jsonItems, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP); ?>
</script>