Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 36c47bb7a6 | |||
| 6031fc0185 | |||
| e77c60d8c8 | |||
| 7f5cea8c1e | |||
| 71c213ef1e | |||
| 0b4c5f988d | |||
| 59eeb05e4b | |||
| 5d8239822a | |||
| 31585511d0 | |||
| 2ec1b70c91 | |||
| 8f8b25249c | |||
| 8be6e6d61c | |||
| bad0c08e6f | |||
| 55695f3f82 | |||
| 74cbc60cbe | |||
| c09c7ecfa3 | |||
| 944e332b49 | |||
| 4306785be9 | |||
| 266b70a094 | |||
| bd8593d212 | |||
| 0d009262b6 | |||
| bb2c368b1f | |||
| a712f5a993 | |||
| 53bee08833 | |||
| 7a2a3ac1e9 | |||
| a5f02c9a6c | |||
| f77f09ec6f | |||
| 535df85cff | |||
| 82e8c8a1a3 | |||
| c0d8fdede6 | |||
| 958ee1c1f5 | |||
| 1dd128d480 | |||
| dca716ddc5 | |||
| c1dd4fce2b | |||
| 16cfa92721 | |||
| 3b2ed78c1c |
+1
-2
@@ -14,7 +14,6 @@
|
||||
?>
|
||||
<h1>404 - Seite nicht vorhanden</h1>
|
||||
<p>
|
||||
Später im Projekt sollen über index.php?pfad= ... der Inhalt der index.php dynamisch gesetzt werden.
|
||||
Alle Content-Links der Navbar führen zunächst hier her. Exemplarisch wurden für die Fächer Informatik, Physik, Mathematik der Content als Seite erstellt und kann über die Navbar ausgekundschaftet werden.
|
||||
Die Seite, nach der du suchst, existiert hier leider nicht. Entweder haben wir sie verlegt, ein hungriger Bug hat sie gefressen, oder du hast dich beim Tippen vertippt. (Wir schieben die Schuld einfach mal ganz unauffällig auf dich.)
|
||||
</p>
|
||||
</main>
|
||||
+3
-6
@@ -11,12 +11,9 @@ include_once 'php/controller/home-controller.php';
|
||||
|
||||
<h1>Home</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
|
||||
dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
|
||||
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
|
||||
consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
|
||||
sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no
|
||||
sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
Schön, dass du da bist. EduForge ist deine digitale Werkstatt für Lernerfolg. Wir unterstützen Schüler und
|
||||
Studierende dabei, die passenden Lernmaterialien zu finden, Wissenslücken zu schließen und Gelerntes gezielt
|
||||
zu vertiefen.
|
||||
</p>
|
||||
|
||||
<!-- Flexbox für aktive Kategorien -->
|
||||
|
||||
@@ -45,8 +45,8 @@ include_once 'php/controller/showArticle-controller.php';
|
||||
</h1>
|
||||
|
||||
<div class="article-view-meta">
|
||||
<?php if (isset($author) && !empty($author)): ?>
|
||||
<span class="article-view-author">Von: <strong><?php echo htmlspecialchars($author); ?></strong></span>
|
||||
<?php if (isset($name) && !empty($name)): ?>
|
||||
<span class="article-view-author">Von: <strong><?php echo htmlspecialchars($name); ?></strong></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
|
||||
+96
-17
@@ -1,32 +1,111 @@
|
||||
<?php
|
||||
include_once "php/controller/showCategory-controller.php";
|
||||
|
||||
$currentSort = isset($sortStyle) ? $sortStyle : 'alphabet';
|
||||
$currentPage = isset($page) ? $page : 1;
|
||||
?>
|
||||
|
||||
<main>
|
||||
<?php include_once "includes/alertMessages.php"?>
|
||||
<noscript>
|
||||
Bitte JavaScript aktivieren!
|
||||
</noscript>
|
||||
|
||||
<h1><?php if (isset($category) && !empty($category)){ echo htmlspecialchars($category); } ?></h1>
|
||||
<!-- Das Formular umschließt jetzt das gesamte Layout -->
|
||||
<form id="search-form-id" action="index.php" method="GET" style="display: contents;">
|
||||
<input type="hidden" name="pfad" value="showCategory">
|
||||
<input type="hidden" name="category" value="<?php echo (isset($category) && !empty($category)) ? htmlspecialchars($category) : ''; ?>">
|
||||
<input type="hidden" id="s-res-page-input" name="page" value="<?php echo $currentPage; ?>">
|
||||
|
||||
<div class="s-res-list">
|
||||
<?php
|
||||
if (!empty($articles)): ?>
|
||||
<div class="cat-view-container">
|
||||
|
||||
<!-- LINKE SPALTE: SEITENLEISTE FÜR SORTIERUNG -->
|
||||
<aside class="cat-sidebar">
|
||||
<div class="cat-sidebar-box">
|
||||
<h3 class="cat-sidebar-title">Sortierung</h3>
|
||||
<div class="cat-filter-group">
|
||||
<label class="cat-filter-option">
|
||||
<input type="radio" name="sort" value="alphabet" <?php echo ($currentSort === 'alphabet') ? 'checked' : ''; ?> onchange="this.form.submit();">
|
||||
Alphabetisch
|
||||
</label>
|
||||
<label class="cat-filter-option">
|
||||
<input type="radio" name="sort" value="likes" <?php echo ($currentSort === 'likes') ? 'checked' : ''; ?> onchange="this.form.submit();">
|
||||
Beliebtheit (Likes)
|
||||
</label>
|
||||
<label class="cat-filter-option">
|
||||
<input type="radio" name="sort" value="newest" <?php echo ($currentSort === 'newest') ? 'checked' : ''; ?> onchange="this.form.submit();">
|
||||
Neueste Beiträge
|
||||
</label>
|
||||
<label class="cat-filter-option">
|
||||
<input type="radio" name="sort" value="oldest" <?php echo ($currentSort === 'oldest') ? 'checked' : ''; ?> onchange="this.form.submit();">
|
||||
Älteste Beiträge
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- RECHTE SPALTE: INHALT & PAGINATOR -->
|
||||
<main class="cat-view-main">
|
||||
<div class="cat-view-header">
|
||||
<h1 class="cat-view-title">Kategorie: <?php echo (isset($category) && !empty($category)) ? htmlspecialchars($category) : 'Unbekannt'; ?></h1>
|
||||
<p class="cat-view-meta-text">
|
||||
<?php echo (isset($totalArticles)) ? $totalArticles : 0; ?> Treffer in dieser Kategorie
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Beiträge -->
|
||||
<div class="cat-view-list">
|
||||
<?php if (isset($articles) && !empty($articles)): ?>
|
||||
<?php foreach ($articles as $article): ?>
|
||||
<div class="s-res-item">
|
||||
<div class="s-res-content">
|
||||
<h2 class="s-res-item-title">
|
||||
<a href="index.php?pfad=showArticle&id=<?php echo $article->getId(); ?>" class="s-res-link">
|
||||
<?php echo htmlspecialchars($article->getTitle()); ?>
|
||||
<div class="cat-view-item">
|
||||
<div class="cat-view-content">
|
||||
<h2 class="cat-view-item-title">
|
||||
<a href="index.php?pfad=showArticle&id=<?php echo htmlspecialchars($article->getID()); ?>" class="cat-view-link">
|
||||
<?php echo (isset($article) && !empty($article->getTitle())) ? htmlspecialchars($article->getTitle()) : 'Kein Titel'; ?>
|
||||
</a>
|
||||
</h2>
|
||||
<p class="s-res-author">Von: <span class="s-res-author-name"><?php echo htmlspecialchars($article->getAuthor()); ?></span></p>
|
||||
|
||||
<div class="cat-view-meta-row">
|
||||
<p class="cat-view-author">
|
||||
von <span class="cat-view-author-name"><?php echo (isset($article) && !empty($article->getAuthor())) ? htmlspecialchars($article->getAuthor()) : 'Anonym'; ?></span>
|
||||
</p>
|
||||
<span class="cat-view-likes">
|
||||
❤️ <?php echo (isset($article) && !empty($article->getLikes())) ? htmlspecialchars($article->getLikes()) : '0'; ?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="s-res-arrow">→</div>
|
||||
|
||||
</div>
|
||||
<div class="cat-view-arrow">→</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php
|
||||
else: ?>
|
||||
<p> Es sind noch keine Beiträge in dieser Kategorie enthalten.</p>
|
||||
<?php else: ?>
|
||||
<p class="cat-view-meta-text">Keine Artikel in dieser Kategorie gefunden.</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<!-- Footer Paginator -->
|
||||
<?php if (isset($totalPages) && $totalPages > 1): ?>
|
||||
<div class="cat-view-pagination-footer">
|
||||
<div></div>
|
||||
<div class="s-res-page-navigation">
|
||||
<button type="button" class="s-res-page-btn" data-page="<?php echo $currentPage - 1; ?>" <?php echo ($currentPage <= 1) ? 'disabled' : ''; ?>>
|
||||
«
|
||||
</button>
|
||||
|
||||
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
|
||||
<button type="button"
|
||||
class="s-res-page-btn <?php echo ($i === $currentPage) ? 'cat-active-btn' : ''; ?>"
|
||||
data-page="<?php echo $i; ?>"
|
||||
<?php echo ($i === $currentPage) ? 'disabled' : ''; ?>>
|
||||
<?php echo $i; ?>
|
||||
</button>
|
||||
<?php endfor; ?>
|
||||
|
||||
<button type="button" class="s-res-page-btn" data-page="<?php echo $currentPage + 1; ?>" <?php echo ($currentPage >= $totalPages) ? 'disabled' : ''; ?>>
|
||||
»
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/* --- ZWEISPALTIIGES GRID-LAYOUT --- */
|
||||
.cat-view-container {
|
||||
box-sizing: border-box;
|
||||
max-width: 95%; /* 95% Monitorbreite wie das Original */
|
||||
width: 95%;
|
||||
margin: 2rem auto;
|
||||
padding: 0 1rem;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
color: #212529;
|
||||
line-height: 1.5;
|
||||
|
||||
/* Grid für die Zweispaltigkeit */
|
||||
display: grid;
|
||||
grid-template-columns: 320px 1fr; /* 320px Sidebar, Rest für Content */
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
.cat-view-container * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* --- SEITENLEISTE (SORTIERUNG) --- */
|
||||
.cat-sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.cat-sidebar-box {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.cat-sidebar-title {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: #1a202c;
|
||||
margin: 0 0 1rem 0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.cat-filter-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.cat-filter-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
cursor: pointer;
|
||||
font-size: 0.95rem;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.cat-filter-option input[type="radio"] {
|
||||
margin: 0;
|
||||
accent-color: #3182ce;
|
||||
}
|
||||
|
||||
/* --- HAUPTINHALT --- */
|
||||
.cat-view-main {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.cat-view-header {
|
||||
margin-bottom: 2rem;
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.cat-view-title {
|
||||
font-size: 2rem;
|
||||
color: #1a202c;
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.cat-view-meta-text {
|
||||
color: #6c757d;
|
||||
font-size: 0.95rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* --- BEITRÄGE LISTE --- */
|
||||
.cat-view-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.cat-view-item {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 1.25rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.cat-view-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
border-color: #cbd5e1;
|
||||
}
|
||||
|
||||
.cat-view-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.cat-view-item-title {
|
||||
font-size: 1.25rem;
|
||||
margin: 0 0 0.25rem 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.cat-view-link {
|
||||
color: #3182ce;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.cat-view-link:hover {
|
||||
text-decoration: underline;
|
||||
color: #2b6cb0;
|
||||
}
|
||||
|
||||
.cat-view-meta-row {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.cat-view-author {
|
||||
font-size: 0.875rem;
|
||||
color: #4a5568;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cat-view-author-name {
|
||||
font-weight: 600;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.cat-view-likes {
|
||||
font-size: 0.9em;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.cat-view-arrow {
|
||||
font-size: 1.5rem;
|
||||
color: #a0aec0;
|
||||
padding-left: 1rem;
|
||||
transition: color 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.cat-view-item:hover .cat-view-arrow {
|
||||
color: #3182ce;
|
||||
transform: translateX(3px);
|
||||
}
|
||||
|
||||
/* --- FOOTER PAGINATION --- */
|
||||
.cat-view-pagination-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 2rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.cat-view-pagination-footer .s-res-page-navigation {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.cat-view-pagination-footer .s-res-page-btn {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #cbd5e1;
|
||||
color: #4a5568;
|
||||
padding: 0.35rem 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.cat-view-pagination-footer .s-res-page-btn:hover:not(:disabled) {
|
||||
background-color: #f8f9fa;
|
||||
border-color: #cbd5e1;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.cat-view-pagination-footer .cat-active-btn {
|
||||
background-color: #3182ce;
|
||||
border-color: #3182ce;
|
||||
color: #ffffff;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.cat-view-pagination-footer .s-res-page-btn:disabled:not(.cat-active-btn) {
|
||||
background-color: #f1f5f9;
|
||||
border-color: #e2e8f0;
|
||||
color: #94a3b8;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* RESPONSIVE ANPASSUNG (Unter 768px) */
|
||||
@media (max-width: 768px) {
|
||||
.cat-view-container {
|
||||
grid-template-columns: 1fr; /* Stapelt Sidebar und Inhalt untereinander */
|
||||
gap: 1.5rem;
|
||||
margin: 1rem auto;
|
||||
}
|
||||
.cat-view-pagination-footer {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,7 @@ if ($pfad === "deleteAccount") {
|
||||
<link rel="stylesheet" href="css/profile.css">
|
||||
<link rel="stylesheet" href="css/showArticle.css">
|
||||
<link rel="stylesheet" href="css/message.css">
|
||||
<link rel="stylesheet" href="css/showCategory.css">
|
||||
|
||||
<script src="js/paginator.js" async></script>
|
||||
<script src="js/sorter.js" async></script>
|
||||
|
||||
+3
-3
@@ -1,13 +1,13 @@
|
||||
console.log("Die JavaScript-Datei wurde erfolgreich geladen!");
|
||||
console.log("editor.js wurde erfolgreich geladen!");
|
||||
|
||||
function initEditor() {
|
||||
const form = document.getElementById("editor-form");
|
||||
|
||||
if (!form) {
|
||||
console.error("Skript abgebrochen: Formular nicht gefunden!");
|
||||
console.error("editor.js wurde abgebrochen: Formular nicht gefunden!");
|
||||
return;
|
||||
} else {
|
||||
console.log("Formular gefunden und Editor initialisiert:", form);
|
||||
console.log("Formular gefunden und editor.js initialisiert:", form);
|
||||
}
|
||||
|
||||
const container = document.getElementById("block-container");
|
||||
|
||||
+223
-21
@@ -1,27 +1,229 @@
|
||||
function initPaginator() {
|
||||
const form = document.getElementById('search-form-id');
|
||||
const pageInput = document.getElementById('s-res-page-input');
|
||||
const pageButtons = document.querySelectorAll('.s-res-page-navigation .s-res-page-btn');
|
||||
console.log("editor.js wurde erfolgreich geladen!");
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
pageButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
if (this.disabled) return;
|
||||
const state = {
|
||||
items: [],
|
||||
sorted: [],
|
||||
category: 'all',
|
||||
sort: 'alphabet',
|
||||
limit: 10,
|
||||
page: 1,
|
||||
};
|
||||
|
||||
const targetPage = this.getAttribute('data-page');
|
||||
|
||||
if (targetPage && form && pageInput) {
|
||||
pageInput.value = targetPage;
|
||||
form.submit();
|
||||
function loadData() {
|
||||
const el = document.getElementById('s-res-data');
|
||||
if (!el) return [];
|
||||
try {
|
||||
return JSON.parse(el.textContent);
|
||||
} catch (e) {
|
||||
console.error('Suchergebnis-Daten konnten nicht gelesen werden', e);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ist das DOM bereits vollständig aufgebaut?
|
||||
if (document.readyState === 'loading') {
|
||||
// Falls noch geladen wird, auf das Event warten
|
||||
function applyFilterAndSort() {
|
||||
let list = state.items.slice();
|
||||
|
||||
if (state.category && state.category !== 'all') {
|
||||
list = list.filter(item => (item.category || '') === state.category);
|
||||
}
|
||||
|
||||
switch (state.sort) {
|
||||
case 'likes':
|
||||
list.sort((a, b) => (b.likes || 0) - (a.likes || 0));
|
||||
break;
|
||||
case 'newest':
|
||||
list.sort((a, b) => (b.creationDate || '').localeCompare(a.creationDate || ''));
|
||||
break;
|
||||
case 'oldest':
|
||||
list.sort((a, b) => (a.creationDate || '').localeCompare(b.creationDate || ''));
|
||||
break;
|
||||
default:
|
||||
list.sort((a, b) => (a.title || '').localeCompare(b.title || '', 'de', { sensitivity: 'base' }));
|
||||
}
|
||||
|
||||
state.sorted = list;
|
||||
const totalPages = Math.max(1, Math.ceil(state.sorted.length / state.limit));
|
||||
state.page = Math.min(Math.max(state.page, 1), totalPages);
|
||||
}
|
||||
|
||||
function el(tag, className, text) {
|
||||
const e = document.createElement(tag);
|
||||
if (className) e.className = className;
|
||||
if (text !== undefined) e.textContent = text;
|
||||
return e;
|
||||
}
|
||||
|
||||
function renderList() {
|
||||
const container = document.querySelector('.s-res-list');
|
||||
if (!container) return;
|
||||
|
||||
const start = (state.page - 1) * state.limit;
|
||||
const pageItems = state.sorted.slice(start, start + state.limit);
|
||||
|
||||
container.innerHTML = '';
|
||||
|
||||
if (pageItems.length === 0) {
|
||||
container.appendChild(el('p', null, 'Keine Beiträge zu diesem Suchbegriff gefunden.'));
|
||||
return;
|
||||
}
|
||||
|
||||
pageItems.forEach(item => {
|
||||
const item_el = el('div', 's-res-item');
|
||||
item_el.dataset.likes = item.likes;
|
||||
item_el.dataset.category = item.category;
|
||||
|
||||
const link = el('a', 's-res-link', item.title);
|
||||
link.href = 'index.php?pfad=showArticle&id=' + encodeURIComponent(item.id);
|
||||
|
||||
const title = el('h2', 's-res-item-title');
|
||||
title.appendChild(link);
|
||||
|
||||
const authorName = el('span', 's-res-author-name', item.author);
|
||||
const author = el('p', 's-res-author', 'Von: ');
|
||||
author.appendChild(authorName);
|
||||
|
||||
const likes = el('span', 's-res-likes', '❤️ ' + item.likes);
|
||||
|
||||
const metaRow = el('div', 's-res-meta-row');
|
||||
metaRow.appendChild(author);
|
||||
metaRow.appendChild(likes);
|
||||
|
||||
const content = el('div', 's-res-content');
|
||||
content.appendChild(title);
|
||||
content.appendChild(metaRow);
|
||||
|
||||
item_el.appendChild(content);
|
||||
item_el.appendChild(el('div', 's-res-arrow', '→'));
|
||||
|
||||
container.appendChild(item_el);
|
||||
});
|
||||
}
|
||||
|
||||
function renderMeta() {
|
||||
const metaEl = document.querySelector('.s-res-meta');
|
||||
const queryInput = document.getElementById('site-search');
|
||||
if (metaEl) {
|
||||
const q = queryInput ? queryInput.value : '';
|
||||
metaEl.textContent = state.sorted.length + ' Treffer für Ihre Suchanfrage "' + q + '"';
|
||||
}
|
||||
}
|
||||
|
||||
function renderPagination() {
|
||||
const nav = document.querySelector('.s-res-page-navigation');
|
||||
if (!nav) return;
|
||||
|
||||
const totalPages = Math.max(1, Math.ceil(state.sorted.length / state.limit));
|
||||
nav.innerHTML = '';
|
||||
|
||||
const makeBtn = (label, page, disabled, active) => {
|
||||
const btn = el('button', 's-res-page-btn' + (active ? ' is-active' : ''), label);
|
||||
btn.type = 'button';
|
||||
btn.disabled = !!disabled;
|
||||
btn.addEventListener('click', () => goToPage(page));
|
||||
return btn;
|
||||
};
|
||||
|
||||
nav.appendChild(makeBtn('«', state.page - 1, state.page <= 1));
|
||||
|
||||
const windowSize = 2;
|
||||
for (let p = 1; p <= totalPages; p++) {
|
||||
const edge = p === 1 || p === totalPages;
|
||||
const near = Math.abs(p - state.page) <= windowSize;
|
||||
if (!edge && !near) {
|
||||
if (p === 2 || p === totalPages - 1) nav.appendChild(el('span', 's-res-page-dots', '…'));
|
||||
continue;
|
||||
}
|
||||
nav.appendChild(makeBtn(String(p), p, false, p === state.page));
|
||||
}
|
||||
|
||||
nav.appendChild(makeBtn('»', state.page + 1, state.page >= totalPages));
|
||||
}
|
||||
|
||||
function updateUrl() {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('sort', state.sort);
|
||||
url.searchParams.set('category', state.category);
|
||||
url.searchParams.set('limit', state.limit);
|
||||
url.searchParams.set('page', state.page);
|
||||
window.history.replaceState(null, '', url);
|
||||
}
|
||||
|
||||
function rerender() {
|
||||
applyFilterAndSort();
|
||||
renderList();
|
||||
renderMeta();
|
||||
renderPagination();
|
||||
updateUrl();
|
||||
}
|
||||
|
||||
function goToPage(page) {
|
||||
const totalPages = Math.max(1, Math.ceil(state.sorted.length / state.limit));
|
||||
state.page = Math.min(Math.max(page, 1), totalPages);
|
||||
renderList();
|
||||
renderPagination();
|
||||
updateUrl();
|
||||
}
|
||||
|
||||
function initPaginator() {
|
||||
state.items = loadData();
|
||||
|
||||
const checkedSort = document.querySelector('.sort-radio:checked');
|
||||
state.sort = checkedSort ? checkedSort.value : 'alphabet';
|
||||
|
||||
const categorySelect = document.getElementById('category-filter');
|
||||
state.category = categorySelect ? categorySelect.value.toLowerCase() : 'all';
|
||||
|
||||
const limitSelect = document.getElementById('s-res-per-page');
|
||||
state.limit = limitSelect ? parseInt(limitSelect.value, 10) || 10 : 10;
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
state.page = parseInt(params.get('page') || '1', 10) || 1;
|
||||
|
||||
document.querySelectorAll('.sort-radio').forEach(radio => {
|
||||
radio.addEventListener('change', function () {
|
||||
state.sort = this.value;
|
||||
state.page = 1;
|
||||
rerender();
|
||||
});
|
||||
});
|
||||
|
||||
if (categorySelect) {
|
||||
categorySelect.addEventListener('change', function () {
|
||||
state.category = this.value.toLowerCase();
|
||||
state.page = 1;
|
||||
rerender();
|
||||
});
|
||||
}
|
||||
|
||||
if (limitSelect) {
|
||||
limitSelect.addEventListener('change', function () {
|
||||
state.limit = parseInt(this.value, 10) || 10;
|
||||
state.page = 1;
|
||||
rerender();
|
||||
});
|
||||
}
|
||||
|
||||
// "Filter anwenden"-Button wird bei aktivem JS nicht gebraucht
|
||||
const applyBtn = document.querySelector('.s-res-apply-btn');
|
||||
if (applyBtn) applyBtn.style.display = 'none';
|
||||
|
||||
// Server-gerenderte Pagination-Links durch clientseitige Steuerung ersetzen
|
||||
document.querySelectorAll('.s-res-page-navigation .s-res-page-btn').forEach(link => {
|
||||
link.addEventListener('click', function (evt) {
|
||||
evt.preventDefault();
|
||||
const target = parseInt(this.getAttribute('data-page'), 10);
|
||||
if (!isNaN(target)) goToPage(target);
|
||||
});
|
||||
});
|
||||
|
||||
rerender();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initPaginator);
|
||||
} else {
|
||||
// Falls das HTML bereits komplett da ist, sofort ausführen
|
||||
} else {
|
||||
initPaginator();
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -2,8 +2,8 @@
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
require_once '../model/LocalArticleManager.php';
|
||||
require_once '../model/ArticleManager.php';
|
||||
require_once '../model/UserManager.php';
|
||||
require_once '../model/Article.php';
|
||||
require_once '../validator/search-validator.php';
|
||||
|
||||
@@ -16,43 +16,18 @@ if ($_SERVER["REQUEST_METHOD"] === "GET" && isset($_GET["q"])) {
|
||||
$_SESSION["message"] = "invalid_search_query";
|
||||
} else {
|
||||
try {
|
||||
|
||||
$articleManager = ArticleManager::getInstance();
|
||||
$userManager = UserManager::getInstance();
|
||||
|
||||
$results = $articleManager->search($search);
|
||||
|
||||
$sortStyle = $_GET['sort'] ?? 'alphabet';
|
||||
$_SESSION['search_sort'] = $sortStyle;
|
||||
|
||||
if ($sortStyle === 'alphabet') {
|
||||
// Titel aufsteigend alphabetiisch sortiert
|
||||
usort($results, function ($a, $b) {
|
||||
return strcasecmp($a->getTitle(), $b->getTitle());
|
||||
});
|
||||
} elseif ($sortStyle === 'likes') {
|
||||
usort($results, function($a, $b) {
|
||||
return $b->getLikeCount() <=> $a->getLikeCount();
|
||||
});
|
||||
} elseif ($sortStyle === 'newest') {
|
||||
// Datum neu zu alt sortiert
|
||||
usort($results, function($a, $b) {
|
||||
return strcmp($b->getCreationDate(), $a->getCreationDate());
|
||||
});
|
||||
} elseif ($sortStyle === 'oldest') {
|
||||
// Datum alt zu neu sortiert
|
||||
usort($results, function($a, $b) {
|
||||
return strcmp($a->getCreationDate(), $b->getCreationDate());
|
||||
});
|
||||
}
|
||||
|
||||
// Ergebnisse werden in ein flaches array umgewandelt, da sont incomplete-PHP error im Ergebnis
|
||||
$safeArrayResults = [];
|
||||
foreach ($results as $obj) {
|
||||
$safeArrayResults[] = [
|
||||
"id" => $obj->getId(),
|
||||
"title" => $obj->getTitle(),
|
||||
"content" => $obj->getContent(),
|
||||
"author" => $obj->getAuthor(),
|
||||
"author" => $userManager->findUser($obj->getAuthor())["vorname"] . " " . $userManager->findUser($obj->getAuthor())["nachname"],
|
||||
"category" => $obj->getCategory(),
|
||||
"tags" => $obj->getTags(),
|
||||
"creationDate" => $obj->getCreationDate(),
|
||||
@@ -64,20 +39,16 @@ if ($_SERVER["REQUEST_METHOD"] === "GET" && isset($_GET["q"])) {
|
||||
$_SESSION["search_query"] = $search;
|
||||
$_SESSION["message"] = "new_search_results";
|
||||
|
||||
} catch (Exception $e){
|
||||
// Bei einer neuen Suche Anzeige-Filter zurücksetzen
|
||||
$_SESSION['search_sort'] = 'alphabet';
|
||||
$_SESSION['search_category'] = 'all';
|
||||
$_SESSION['search_limit'] = 10;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$_SESSION["message"] = "internal_error";
|
||||
}
|
||||
}
|
||||
|
||||
$sort = $_GET['sort'] ?? 'alphabet';
|
||||
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
|
||||
if (!searchLimitValidator($limit)) {
|
||||
$limit = 10;
|
||||
}
|
||||
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||
header("Location: ../../index.php?pfad=search-results&q=" . urlencode($search) . "&sort=" . urlencode($sort) . "&limit=" . $limit . "&page=" . $page);
|
||||
header("Location: ../../index.php?pfad=search-results&q=" . urlencode($search));
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -5,6 +5,7 @@ if (session_status() === PHP_SESSION_NONE) {
|
||||
|
||||
require_once 'php/model/Article.php';
|
||||
require_once 'php/model/ArticleManager.php';
|
||||
require_once 'php/model/UserManager.php';
|
||||
require_once 'php/model/CommentManager.php';
|
||||
|
||||
if (isset($_GET["id"]) && !empty($_GET["id"])){
|
||||
@@ -19,6 +20,9 @@ if (isset($_GET["id"]) && !empty($_GET["id"])){
|
||||
$author = $article->getAuthor();
|
||||
$tags = $article->getTags();
|
||||
$articleObj = $article; // Objekt für die Like-Abfagen sichern
|
||||
|
||||
$userManager = UserManager::getInstance();
|
||||
$name = $userManager->findUser($author)["vorname"]." ".$userManager->findUser($author)["nachname"];
|
||||
}else{
|
||||
//header("location: index.php?pfad=404");
|
||||
include_once "content/404.php";
|
||||
|
||||
@@ -1,19 +1,65 @@
|
||||
<?php
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once 'php/model/Article.php';
|
||||
require_once 'php/model/ArticleManager.php';
|
||||
require_once 'php/model/UserManager.php';
|
||||
require_once 'php/validator/article-validator.php';
|
||||
|
||||
if (isset($_GET["category"]) && !empty($_GET["category"]) && articleCategoryValidator($_GET["category"])){
|
||||
$category = $_GET["category"];
|
||||
|
||||
// Sortierung auslesen (Standard: alphabet)
|
||||
$sortStyle = isset($_GET['sort']) ? trim($_GET['sort']) : 'alphabet';
|
||||
|
||||
// Aktuelle Seite auslesen
|
||||
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||
if ($page < 1) { $page = 1; }
|
||||
|
||||
try {
|
||||
$articleManager = ArticleManager::getInstance();
|
||||
$articles = $articleManager->getArticlesByCategory($category);
|
||||
$userManager = UserManager::getInstance();
|
||||
$allArticles = $articleManager->getArticlesByCategory($category);
|
||||
foreach ($allArticles as $article) {
|
||||
$article->setAuthor($userManager->findUser($article->getAuthor())["vorname"] . " " . $userManager->findUser($article->getAuthor())["nachname"]);
|
||||
}
|
||||
$totalArticles = count($allArticles);
|
||||
|
||||
// --- SORTIERUNG LOGIK ---
|
||||
if ($sortStyle === 'alphabet') {
|
||||
usort($allArticles, function($a, $b) {
|
||||
return strcasecmp($a->getTitle(), $b->getTitle());
|
||||
});
|
||||
} elseif ($sortStyle === 'likes') {
|
||||
usort($allArticles, function($a, $b) {
|
||||
return $b->getLikes() <=> $a->getLikes(); // Absteigend nach Likes
|
||||
});
|
||||
} elseif ($sortStyle === 'newest') {
|
||||
usort($allArticles, function($a, $b) {
|
||||
return strtotime($b->getCreationDate()) <=> strtotime($a->getCreationDate()); // Neueste zuerst
|
||||
});
|
||||
} elseif ($sortStyle === 'oldest') {
|
||||
usort($allArticles, function($a, $b) {
|
||||
return strtotime($a->getCreationDate()) <=> strtotime($b->getCreationDate()); // Älteste zuerst
|
||||
});
|
||||
}
|
||||
|
||||
// Paginierung konfigurieren
|
||||
$limit = 10;
|
||||
$totalPages = ceil($totalArticles / $limit);
|
||||
if ($page > $totalPages && $totalPages > 0) { $page = $totalPages; }
|
||||
|
||||
$offset = ($page - 1) * $limit;
|
||||
$articles = array_slice($allArticles, $offset, $limit);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$_SESSION["message"] = "internal_error";
|
||||
include_once "content/404.php";
|
||||
exit();
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
$_SESSION["message"] = "invalid_category";
|
||||
include_once "content/404.php";
|
||||
exit();
|
||||
|
||||
@@ -97,6 +97,16 @@ class Article
|
||||
return $this->author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt einen neuen Autor eines Beitrages.
|
||||
* @param string $author
|
||||
* @return void
|
||||
*/
|
||||
public function setAuthor(string $author)
|
||||
{
|
||||
$this->author = $author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt das Veröffentlichungsdatum des Beitrags zurück.
|
||||
* @return string
|
||||
|
||||
Reference in New Issue
Block a user