107 lines
3.7 KiB
JavaScript
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();
|
|
})();
|