66 lines
3.4 KiB
Plaintext
66 lines
3.4 KiB
Plaintext
<%#
|
|
Pagination footer: rows-per-page (GET form) + page numbers. Query-param driven, zero-JS.
|
|
Page items are <a>, inert ones (current/ellipsis/disabled) aren't.
|
|
Config (all optional; never throws):
|
|
label? nav aria-label (default "Pagination")
|
|
summary? { from, to, total } → the pagination.summary message
|
|
rows? { name, value?, options, label?, submitLabel?, action?, hidden? } rows-per-page form
|
|
options: (number | { value, label })[]; hidden: { name, value }[] carries list state
|
|
prev?, next? { href? } page step; omit href ⇒ disabled
|
|
pages? { label, href?, current?, ellipsis? }[]
|
|
Every href is run through localeHref, and the rows form carries the locale as a hidden input —
|
|
a GET submit replaces the whole query string, so it would drop the visitor's language otherwise.
|
|
%><%
|
|
const label = locals.label || t("pagination.label");
|
|
const summary = locals.summary;
|
|
const rows = locals.rows;
|
|
const prev = locals.prev;
|
|
const next = locals.next;
|
|
const pages = locals.pages || [];
|
|
const eq = (a, b) => String(a ?? "") === String(b);
|
|
-%>
|
|
<footer class="pager">
|
|
<% if (summary) { -%>
|
|
<span><%- t("pagination.summary", { from: summary.from, to: summary.to, total: summary.total }) %></span>
|
|
<% } -%>
|
|
<% if (rows) { -%>
|
|
<form class="pager-rows" method="get"<% if (rows.action) { %> action="<%= localeHref(rows.action) %>"<% } %>>
|
|
<% (rows.hidden || []).forEach((h) => { -%>
|
|
<input type="hidden" name="<%= h.name %>" value="<%= h.value %>">
|
|
<% }) -%>
|
|
<% if (localeParam) { -%>
|
|
<input type="hidden" name="locale" value="<%= localeParam %>">
|
|
<% } -%>
|
|
<label for="pager-rows"><%= rows.label || t("pagination.rows") %></label>
|
|
<span class="select"><select id="pager-rows" name="<%= rows.name %>"><% (rows.options || []).forEach((o) => { const v = o && o.value != null ? o.value : o; const text = o && o.label != null ? o.label : o; %><option value="<%= v %>"<% if (eq(rows.value, v)) { %> selected<% } %>><%= text %></option><% }) %></select></span>
|
|
<button class="page-btn" type="submit"><%= rows.submitLabel || t("pagination.go") %></button>
|
|
</form>
|
|
<% } -%>
|
|
<div class="spacer"></div>
|
|
<nav class="page-nums" aria-label="<%= label %>">
|
|
<% if (prev) { -%>
|
|
<% if (prev.href) { -%>
|
|
<a class="page-btn" href="<%= localeHref(prev.href) %>" aria-label="<%= t("pagination.previous") %>"><svg class="ico ico-sm" style="transform:rotate(180deg)"><use href="#i-chev"/></svg></a>
|
|
<% } else { -%>
|
|
<button class="page-btn" type="button" disabled aria-label="<%= t("pagination.previous") %>"><svg class="ico ico-sm" style="transform:rotate(180deg)"><use href="#i-chev"/></svg></button>
|
|
<% } -%>
|
|
<% } -%>
|
|
<% pages.forEach((p) => { -%>
|
|
<% if (p.ellipsis) { -%>
|
|
<span class="page-btn" aria-hidden="true"><%= p.label || "…" %></span>
|
|
<% } else if (p.current) { -%>
|
|
<span class="page-btn" aria-current="page"><%= p.label %></span>
|
|
<% } else { -%>
|
|
<a class="page-btn" href="<%= localeHref(p.href) %>"><%= p.label %></a>
|
|
<% } -%>
|
|
<% }) -%>
|
|
<% if (next) { -%>
|
|
<% if (next.href) { -%>
|
|
<a class="page-btn" href="<%= localeHref(next.href) %>" aria-label="<%= t("pagination.next") %>"><svg class="ico ico-sm"><use href="#i-chev"/></svg></a>
|
|
<% } else { -%>
|
|
<button class="page-btn" type="button" disabled aria-label="<%= t("pagination.next") %>"><svg class="ico ico-sm"><use href="#i-chev"/></svg></button>
|
|
<% } -%>
|
|
<% } -%>
|
|
</nav>
|
|
</footer>
|