Skip to content

Instantly share code, notes, and snippets.

@wini2
Last active November 8, 2024 17:38
Show Gist options
  • Save wini2/0d05cf8e7f29c0691e691a754d89461f to your computer and use it in GitHub Desktop.
Save wini2/0d05cf8e7f29c0691e691a754d89461f to your computer and use it in GitHub Desktop.
Sliding pagination with javascript for TYPO3 v13 indexed_search
<f:comment>angepasste version für TYPO3 v13 indexed_search fix für ergebnisanzahl u.a. script-einbindung mit inline fkt., ohne gibt' fehler wg. mime-type, nosniff, wenn im Public-Ordner der Kopie --> muss im Public-ordner der eigenen Ext. sein!!</f:comment>
<html
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true"
>
<f:asset.script identifier="indexed_search_pagination" src="EXT:indexed_search/Resources/Public/JavaScript/pagination.js" />
<f:asset.script identifier="indexed_search_sliding_pagination" src="EXT:my_sitepackage/Resources/Public/JavaScript/slideingpagination-indexed-search.js" />
<f:alias map="{sword: searchParams.sword}">
<f:render partial="Form" arguments="{_all}" />
</f:alias>
<f:for each="{resultsets}" as="result" key="freeIndexUid">
<f:if condition="{result.categoryTitle}">
<h1 class="tx-indexedsearch-category">{result.categoryTitle}</h1>
</f:if>
<f:if condition="{result.count} > 0">
<div class="tx-indexedsearch-info-sword">
<f:for each="{searchWords}" as="searchWord" key="key">
<f:if condition="{key} > 0">
<f:then>
<f:translate key="searchFor.{searchWord.operatorLabel}" />&nbsp;<span class="tx-indexedsearch-info-sword-word">{searchWord.sword}</span>
</f:then>
<f:else>
<f:translate key="searchFor" />&nbsp;<span class="tx-indexedsearch-info-sword-word">{searchWord.sword}</span>
</f:else>
</f:if>
</f:for>
</div>
</f:if>
{result.searchedInSectionInfo}
<f:if condition="{result.count} > 0">
<f:then>
<f:comment> Ergenbinisbereich oben suche nach... Anzeige der Erg. von bis von insges.</f:comment>
<div class="tx-indexedsearch-browsebox">
<f:sanitize.html>
<f:translate key="displayResults" arguments="{0: result.pagination.startRecordNumber, 1: result.pagination.endRecordNumber, 2: result.count}" />
</f:sanitize.html>
<f:comment> Ergenbinisbereich oben suche nach... Anzeige der Erg. von bis von insges. ende </f:comment>
<!-- render the anchor-links to the sections inside the displayed result rows -->
<f:if condition="{result.affectedSections}">
<div class="tx-indexedsearch-sectionlinks">
<table cellpadding="0" cellspacing="0" border="0" summary="Result links">
<f:for each="{result.affectedSections}" as="sectionData" key="sectionId">
<tr>
<td width="100%">&gt;&nbsp;
<f:link.page section="anchor_{sectionId}" addQueryString="1"
argumentsToBeExcludedFromQueryString="{0: 'id'}">
<f:if condition="{sectionData.0}">
<f:then>{sectionData.0}</f:then>
<f:else><f:translate key="unnamedSection" /></f:else>
</f:if>
&nbsp;({sectionData.1}&nbsp;<f:translate key="{f:if(condition: '{sectionData.1} > 1', then: 'result.pages', else: 'result.page')}" />)
</f:link.page>
</td>
</tr>
</f:for>
</table>
</div>
</f:if>
<f:render partial="Pagination" arguments="{pagination: result.pagination, searchParams: searchParams}" />
</div>
<f:for each="{result.rows}" as="row">
<f:if condition="{row.isSectionHeader}">
<f:then>
<div id="anchor_{row.sectionId}" class="tx-indexedsearch-sectionhead">
<h2 class="tx-indexedsearch-title"><f:format.html>{row.sectionTitle}</f:format.html> <span class="tx-indexedsearch-result-count">{row.numResultRows} <f:translate key="{f:if(condition: '{row.numResultRows} > 1', then: 'result.pages', else: 'result.page')}" /></span></h2>
</div>
</f:then>
<f:else>
<f:render partial="Searchresult" arguments="{row: row, searchParams: searchParams, firstRow: firstRow}" />
</f:else>
</f:if>
</f:for>
<f:comment><div class="tx-indexedsearch-browsebox">
<f:render partial="Pagination" arguments="{pagination: result.pagination, searchParams: searchParams, freeIndexUid: freeIndexUid}" />
</div></f:comment>
<div class="pagination-wrapper">
<f:render partial="Pagination" arguments="{pagination: result.pagination, searchParams: searchParams}" />
</div>
</f:then>
<f:else>
<div class="tx-indexedsearch-info-noresult">
<f:translate key="result.noResult" />
</div>
</f:else>
</f:if>
</f:for>
</html>
/*
sliding paginator - nur für suchseite (statt im allgem setup über page.footerData.xxxxxx = TEXT) wg. csp hier und nicht im public-verzeichnis des ausgelagerten indexed_search-Resources-Ordner) im Public/JavaScript-Ordner des eigenen sitepackage abgespeichert. Einbindung über <f:asset.script...
*/
document.addEventListener("DOMContentLoaded", function () {
const paginators = document.querySelectorAll(".sliding-paginator");
if (!paginators.length) {
console.log("Keine Paginatoren gefunden");
return;
}
paginators.forEach((paginator) => {
const pageItems = paginator.querySelectorAll(".page-item");
const activePageItem = paginator.querySelector(".page-item.active");
if (!activePageItem) {
console.log("Keine aktive Seite gefunden");
return;
}
const activePage = parseInt(activePageItem.textContent);
const totalPages = Array.from(pageItems).filter(item => !isNaN(parseInt(item.textContent))).length;
if (totalPages <= 5) {
console.log("Zu wenige Seiten für Ellipsen");
return;
}
function createPageItem(pageNum, isCurrent) {
const li = document.createElement("li");
li.classList.add("tx-indexedsearch-browselist-next", "page-item");
if (isCurrent) li.classList.add("active");
const link = document.createElement("a");
link.href = "#";
link.classList.add("tx-indexedsearch-page-selector", "page-link");
link.textContent = pageNum;
link.setAttribute("data-prefix", "tx_indexedsearch");
link.setAttribute("data-pointer", pageNum - 1);
li.appendChild(link);
return li;
}
function createEllipsis() {
const li = document.createElement("li");
li.classList.add("page-item", "ellipsis");
li.innerHTML = "<span class='page-link'>...</span>";
return li;
}
// Neues <ul> erstellen, um das HTML sauber zu halten
const newUl = document.createElement("ul");
newUl.className = paginator.querySelector("ul").className;
// Vorherige und erste Seite Buttons hinzufügen
const firstPageButton = paginator.querySelector(".page-item:first-child");
const prevPageButton = paginator.querySelector(".page-item:nth-child(2)");
if (firstPageButton) newUl.appendChild(firstPageButton.cloneNode(true));
if (prevPageButton) newUl.appendChild(prevPageButton.cloneNode(true));
// Erste Seite immer anzeigen
newUl.appendChild(createPageItem(1, activePage === 1));
// Ellipse vor dem aktuellen Bereich, wenn nötig
if (activePage > 3) {
newUl.appendChild(createEllipsis());
}
// Seiten um die aktuelle Seite herum anzeigen
const startPage = Math.max(2, activePage - 1);
const endPage = Math.min(totalPages - 1, activePage + 1);
for (let i = startPage; i <= endPage; i++) {
newUl.appendChild(createPageItem(i, i === activePage));
}
// Ellipse nach dem aktuellen Bereich, wenn nötig
if (activePage < totalPages - 2) {
newUl.appendChild(createEllipsis());
}
// Letzte Seite immer anzeigen
newUl.appendChild(createPageItem(totalPages, activePage === totalPages));
// 'Nächste Seite' und 'Letzte Seite' Buttons am Ende hinzufügen
const nextPageButton = paginator.querySelector(".next-page");
const lastPageButton = paginator.querySelector(".last-page");
if (nextPageButton) newUl.appendChild(nextPageButton.cloneNode(true));
if (lastPageButton) newUl.appendChild(lastPageButton.cloneNode(true));
// Ersetze das alte <ul> mit dem neuen <ul>
paginator.replaceChild(newUl, paginator.querySelector("ul"));
console.log("Neuer Paginator hinzugefügt:", newUl);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment