Files
谢宇宁andClaude Opus 5.5 0fbdba5ccf Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:47:47 +07:00

107 lines
3.7 KiB
JavaScript

(function () {
var grid = document.querySelector('[data-search-grid]');
if (!grid) return;
var cards = Array.from(grid.querySelectorAll('.search-card'));
var pagination = document.querySelector('[data-pagination]');
var pageNumbers = pagination.querySelector('[data-page-numbers]');
var previous = pagination.querySelector('[data-page-prev]');
var next = pagination.querySelector('[data-page-next]');
var results = document.querySelector('.search-results');
var page = pageFromURL();
function pageFromURL() {
var match = window.location.pathname.match(/\/page\/(\d+)\/?$/);
var value = match ? Number(match[1]) : 1;
return Number.isInteger(value) && value > 0 ? value : 1;
}
function updateURL(replace) {
var basePath = window.location.pathname.replace(/\/page\/\d+\/?$/, '').replace(/\/$/, '');
var path = basePath || '/search';
if (page > 1) path += '/page/' + String(page);
if (path !== window.location.pathname) {
window.history[replace ? 'replaceState' : 'pushState']({}, '', path);
}
}
function pageTokens(total, mobile) {
var tokens = [];
var visibleEdge = mobile ? 3 : 5;
var i;
if (total <= visibleEdge + 2) {
for (i = 1; i <= total; i++) tokens.push(i);
} else if (page <= (mobile ? 2 : 3)) {
for (i = 1; i <= visibleEdge; i++) tokens.push(i);
tokens.push('ellipsis', total);
} else if (page >= total - (mobile ? 1 : 2)) {
tokens.push(1, 'ellipsis');
for (i = total - visibleEdge + 1; i <= total; i++) tokens.push(i);
} else if (mobile) {
tokens.push(1, 'ellipsis', page, 'ellipsis', total);
} else {
tokens.push(1, 'ellipsis', page - 1, page, page + 1, 'ellipsis', total);
}
return tokens;
}
function render() {
var mobile = window.matchMedia('(max-width: 900px)').matches;
var pageSize = mobile ? 9 : 12;
var totalPages = Math.max(1, Math.ceil(cards.length / pageSize));
var start;
if (page > totalPages) {
page = totalPages;
updateURL(true);
}
start = (page - 1) * pageSize;
cards.forEach(function (card, index) {
card.hidden = index < start || index >= start + pageSize;
});
previous.disabled = page === 1;
next.disabled = page === totalPages;
pageNumbers.replaceChildren();
pageTokens(totalPages, mobile).forEach(function (token) {
if (token === 'ellipsis') {
var dots = document.createElement('span');
dots.className = 'search-pagination__ellipsis';
dots.textContent = '…';
dots.setAttribute('aria-hidden', 'true');
pageNumbers.appendChild(dots);
return;
}
var button = document.createElement('button');
button.type = 'button';
button.textContent = String(token);
button.setAttribute('aria-label', '第 ' + token + ' 页');
if (token === page) {
button.className = 'is-current';
button.setAttribute('aria-current', 'page');
}
button.addEventListener('click', function () { goToPage(token); });
pageNumbers.appendChild(button);
});
}
function goToPage(number) {
var totalPages = Math.max(1, Math.ceil(cards.length / (window.matchMedia('(max-width: 900px)').matches ? 9 : 12)));
if (number < 1 || number > totalPages || number === page) return;
page = number;
updateURL(false);
render();
results.scrollIntoView({ block: 'start' });
}
previous.addEventListener('click', function () { goToPage(page - 1); });
next.addEventListener('click', function () { goToPage(page + 1); });
window.addEventListener('popstate', function () {
page = pageFromURL();
render();
});
window.addEventListener('resize', render);
render();
})();