revert
This commit is contained in:
+203
-227
@@ -1,242 +1,218 @@
|
||||
console.log("paginator.js wurde erfolgreich geladen!");
|
||||
(function () {
|
||||
'use strict';
|
||||
// Globale Variablen für den JavaScript-Betrieb
|
||||
let allItems = [];
|
||||
let filteredItems = [];
|
||||
let currentJsPage = 1;
|
||||
let jsLimit = 10;
|
||||
|
||||
const state = {
|
||||
items: [],
|
||||
sorted: [],
|
||||
category: 'all',
|
||||
sort: 'alphabet',
|
||||
limit: 10,
|
||||
page: 1,
|
||||
};
|
||||
function initPaginator() {
|
||||
const dataContainer = document.getElementById('search-data-json');
|
||||
if (!dataContainer) return;
|
||||
|
||||
function loadData() {
|
||||
const el = document.getElementById('s-res-data');
|
||||
console.log("s-res-data Element:", el);
|
||||
if (!el) { console.error('s-res-data Element nicht gefunden'); return []; }
|
||||
const raw = el.textContent.trim();
|
||||
console.log("Roher Inhalt (erste 500 Zeichen):", raw.slice(0, 500));
|
||||
console.log("Roher Inhalt Länge:", raw.length);
|
||||
if (!raw) { console.error('s-res-data ist leer'); return []; }
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
console.log("Geparst, Anzahl Elemente:", parsed.length);
|
||||
return parsed;
|
||||
} catch (e) {
|
||||
console.error('JSON.parse fehlgeschlagen:', e, raw.slice(0, 200));
|
||||
return [];
|
||||
}
|
||||
// 1. Daten aus PHP-JSON-Schnittstelle laden
|
||||
try {
|
||||
allItems = JSON.parse(dataContainer.textContent);
|
||||
} catch (e) {
|
||||
console.error("Fehler beim Laden der Suchdaten:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
function applyFilterAndSort() {
|
||||
let list = state.items.slice();
|
||||
// 2. Event-Listener für Live-Interaktionen im Browser registrieren
|
||||
const sortRadios = document.querySelectorAll('.sort-radio');
|
||||
const categorySelect = document.getElementById('category-filter');
|
||||
const limitSelect = document.getElementById('s-res-per-page');
|
||||
|
||||
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);
|
||||
sortRadios.forEach(radio => radio.addEventListener('change', applyFiltersAndRender));
|
||||
if (categorySelect) categorySelect.addEventListener('change', applyFiltersAndRender);
|
||||
if (limitSelect) {
|
||||
limitSelect.addEventListener('change', function() {
|
||||
jsLimit = parseInt(this.value) || 10;
|
||||
currentJsPage = 1; // Zurück auf Seite 1 bei Limit-Wechsel
|
||||
applyFiltersAndRender();
|
||||
});
|
||||
}
|
||||
|
||||
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 + '"';
|
||||
}
|
||||
}
|
||||
// Pfeil-Navigation (Vor / Zurück) abfangen
|
||||
const prevBtn = document.getElementById('prev-page-btn');
|
||||
const nextBtn = document.getElementById('next-page-btn');
|
||||
|
||||
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;
|
||||
if (prevBtn) {
|
||||
prevBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
if (currentJsPage > 1) {
|
||||
currentJsPage--;
|
||||
renderListAndPagination();
|
||||
}
|
||||
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() {
|
||||
console.log("initPaginator gestartet");
|
||||
state.items = loadData();
|
||||
console.log("Geladene Items:", state.items);
|
||||
|
||||
const checkedSort = document.querySelector('.sort-radio:checked');
|
||||
console.log("checkedSort:", checkedSort);
|
||||
state.sort = checkedSort ? checkedSort.value : 'alphabet';
|
||||
|
||||
const categorySelect = document.getElementById('category-filter');
|
||||
console.log("categorySelect:", categorySelect);
|
||||
state.category = categorySelect ? categorySelect.value.toLowerCase() : 'all';
|
||||
|
||||
const limitSelect = document.getElementById('s-res-per-page');
|
||||
console.log("limitSelect:", limitSelect);
|
||||
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();
|
||||
console.log("initPaginator abgeschlossen, State:", state);
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initPaginator);
|
||||
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 {
|
||||
initPaginator();
|
||||
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">→</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
|
||||
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, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
// DOM-Ready Check
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initPaginator);
|
||||
} else {
|
||||
initPaginator();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user