203 lines
7.5 KiB
JavaScript
203 lines
7.5 KiB
JavaScript
/**
|
|
* Übernimmt Filterung (Kategorie), Sortierung und Pagination der
|
|
* Suchergebnisse vollständig clientseitig, ohne Neuladen der Seite.
|
|
*
|
|
* Voraussetzung: Im HTML liegt ein <script type="application/json" id="s-res-data">
|
|
* mit allen Treffern der aktuellen Suche (siehe content/search-results.php).
|
|
*
|
|
* Ist kein JavaScript aktiv, bleibt die serverseitig gerenderte Ausgabe
|
|
* (inkl. echter Pagination-Links und Formular-Submit) unverändert nutzbar.
|
|
*/
|
|
(function () {
|
|
const DEFAULT_PER_PAGE = 10;
|
|
|
|
const state = {
|
|
all: [],
|
|
filtered: [],
|
|
category: 'all',
|
|
sort: 'alphabet',
|
|
perPage: DEFAULT_PER_PAGE,
|
|
page: 1,
|
|
};
|
|
|
|
const els = {};
|
|
|
|
function init() {
|
|
const dataScript = document.getElementById('s-res-data');
|
|
const listContainer = document.querySelector('.s-res-list');
|
|
if (!dataScript || !listContainer) {
|
|
return; // keine Ergebnisliste auf dieser Seite vorhanden
|
|
}
|
|
|
|
try {
|
|
state.all = JSON.parse(dataScript.textContent);
|
|
} catch (e) {
|
|
console.error('Suchergebnis-Daten konnten nicht gelesen werden.', e);
|
|
return;
|
|
}
|
|
|
|
els.list = listContainer;
|
|
els.categorySelect = document.getElementById('category-filter');
|
|
els.perPageSelect = document.getElementById('s-res-per-page');
|
|
els.sortRadios = document.querySelectorAll('.sort-radio');
|
|
els.pagerContainer = document.querySelector('.s-res-page-navigation');
|
|
els.metaCount = document.querySelector('.s-res-meta');
|
|
|
|
// Ausgangszustand aus dem serverseitig gerenderten Markup übernehmen,
|
|
// damit Browser-zurück / geteilte Links konsistent bleiben.
|
|
if (els.categorySelect) state.category = els.categorySelect.value || 'all';
|
|
if (els.perPageSelect) state.perPage = parseInt(els.perPageSelect.value, 10) || DEFAULT_PER_PAGE;
|
|
const checkedSort = document.querySelector('.sort-radio:checked');
|
|
if (checkedSort) state.sort = checkedSort.value;
|
|
|
|
// Ab hier übernimmt JS: Formular-Steuerelemente lösen keinen
|
|
// Seiten-Reload mehr aus, sondern rendern direkt neu.
|
|
if (els.categorySelect) {
|
|
els.categorySelect.addEventListener('change', function () {
|
|
state.category = this.value;
|
|
state.page = 1;
|
|
render();
|
|
});
|
|
}
|
|
if (els.perPageSelect) {
|
|
els.perPageSelect.addEventListener('change', function () {
|
|
state.perPage = parseInt(this.value, 10) || DEFAULT_PER_PAGE;
|
|
state.page = 1;
|
|
render();
|
|
});
|
|
}
|
|
els.sortRadios.forEach(function (radio) {
|
|
radio.addEventListener('change', function () {
|
|
state.sort = this.value;
|
|
state.page = 1;
|
|
render();
|
|
});
|
|
});
|
|
|
|
render();
|
|
}
|
|
|
|
function sortItems(items, sortValue) {
|
|
const copy = items.slice();
|
|
switch (sortValue) {
|
|
case 'likes':
|
|
copy.sort(function (a, b) { return (b.likes || 0) - (a.likes || 0); });
|
|
break;
|
|
case 'newest':
|
|
copy.sort(function (a, b) { return (b.creationDate || '').localeCompare(a.creationDate || ''); });
|
|
break;
|
|
case 'oldest':
|
|
copy.sort(function (a, b) { return (a.creationDate || '').localeCompare(b.creationDate || ''); });
|
|
break;
|
|
case 'alphabet':
|
|
default:
|
|
copy.sort(function (a, b) { return a.title.localeCompare(b.title, 'de', { sensitivity: 'base' }); });
|
|
break;
|
|
}
|
|
return copy;
|
|
}
|
|
|
|
function render() {
|
|
let items = state.all;
|
|
if (state.category && state.category !== 'all') {
|
|
items = items.filter(function (it) {
|
|
return (it.category || '').toLowerCase() === state.category.toLowerCase();
|
|
});
|
|
}
|
|
state.filtered = sortItems(items, state.sort);
|
|
|
|
const totalResults = state.filtered.length;
|
|
const totalPages = Math.max(1, Math.ceil(totalResults / state.perPage));
|
|
if (state.page > totalPages) state.page = totalPages;
|
|
if (state.page < 1) state.page = 1;
|
|
|
|
const start = (state.page - 1) * state.perPage;
|
|
const pageItems = state.filtered.slice(start, start + state.perPage);
|
|
|
|
renderList(pageItems);
|
|
renderPager(totalPages);
|
|
renderMeta(totalResults);
|
|
}
|
|
|
|
function renderList(items) {
|
|
els.list.innerHTML = '';
|
|
|
|
if (items.length === 0) {
|
|
const p = document.createElement('p');
|
|
p.textContent = 'Keine Beiträge zu diesem Suchbegriff gefunden.';
|
|
els.list.appendChild(p);
|
|
return;
|
|
}
|
|
|
|
items.forEach(function (item) {
|
|
const div = document.createElement('div');
|
|
div.className = 's-res-item';
|
|
div.setAttribute('data-likes', item.likes || 0);
|
|
div.setAttribute('data-category', (item.category || '').toLowerCase());
|
|
|
|
div.innerHTML =
|
|
'<div class="s-res-content">' +
|
|
'<h2 class="s-res-item-title">' +
|
|
'<a class="s-res-link"></a>' +
|
|
'</h2>' +
|
|
'<div class="s-res-meta-row">' +
|
|
'<p class="s-res-author">Von: <span class="s-res-author-name"></span></p>' +
|
|
'<span class="s-res-likes"></span>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'<div class="s-res-arrow">→</div>';
|
|
|
|
const link = div.querySelector('.s-res-link');
|
|
link.href = 'index.php?pfad=showArticle&id=' + encodeURIComponent(item.id);
|
|
link.textContent = item.title;
|
|
div.querySelector('.s-res-author-name').textContent = item.author;
|
|
div.querySelector('.s-res-likes').textContent = item.likes || 0;
|
|
|
|
els.list.appendChild(div);
|
|
});
|
|
}
|
|
|
|
function renderPager(totalPages) {
|
|
if (!els.pagerContainer) return;
|
|
els.pagerContainer.innerHTML = '';
|
|
|
|
const prevBtn = document.createElement('button');
|
|
prevBtn.type = 'button';
|
|
prevBtn.className = 's-res-page-btn';
|
|
prevBtn.textContent = '\u00AB';
|
|
prevBtn.disabled = state.page <= 1;
|
|
prevBtn.addEventListener('click', function () { goToPage(state.page - 1); });
|
|
els.pagerContainer.appendChild(prevBtn);
|
|
|
|
const span = document.createElement('span');
|
|
span.id = 'dynamic-page-numbers';
|
|
span.textContent = 'Seite ' + state.page + ' von ' + totalPages;
|
|
els.pagerContainer.appendChild(span);
|
|
|
|
const nextBtn = document.createElement('button');
|
|
nextBtn.type = 'button';
|
|
nextBtn.className = 's-res-page-btn';
|
|
nextBtn.textContent = '\u00BB';
|
|
nextBtn.disabled = state.page >= totalPages;
|
|
nextBtn.addEventListener('click', function () { goToPage(state.page + 1); });
|
|
els.pagerContainer.appendChild(nextBtn);
|
|
}
|
|
|
|
function renderMeta(totalResults) {
|
|
if (!els.metaCount) return;
|
|
const query = els.metaCount.getAttribute('data-query') || '';
|
|
els.metaCount.textContent = totalResults + ' Treffer für Ihre Suchanfrage "' + query + '"';
|
|
}
|
|
|
|
function goToPage(page) {
|
|
state.page = page;
|
|
render();
|
|
els.list.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
} else {
|
|
init();
|
|
}
|
|
})(); |