Pagination fixes, blog page chooser, Events & Projects redesign
Pagination - Fix the broken mobile layout on News & Projects: page numbers on top, Previous / Next side-by-side below (shared .pagination component) - Add a page chooser to the Blog: rewrite blog-filter.js to combine the topic filter with client-side pagination (page size 6), add the pager markup (all 3 languages) and .blog-pagination styles; it auto-hides when a topic has one page Events & Projects — match the Blog/News design - Hero: uppercase letter-spaced eyebrow, sentence-case bold title, lead subtitle, soft gradient; drop the redundant hero subscribe form and the placeholder copy (signup still available in the bottom newsletter CTA); align MK/SI titles to "Events & projects" - Filters: News-style pills (dark active), left-aligned, with the thin separator line below; .filter-inner wrapper aligns pills/separator with the grid - Spacing: reduce the gap under the header, add space below the filter so the separator / Events sub-filter no longer collide with "All our projects" (these hero/spacing tweaks also tidy the shared About/Get-to-know/ Timeline heroes) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
9e8cbc5876
commit
e1d596751a
9 files changed
+213
-126
No files matched your search
+77
-8
@@ -1,22 +1,91 @@
|
||||
/* Blog topic filter: chips toggle which cards are shown. No dependencies. */
|
||||
/* Blog: topic filter + client-side pagination (they work together).
|
||||
Chips toggle the visible topic; the pager pages through the matches. */
|
||||
(function () {
|
||||
var list = document.querySelector('.blog-list');
|
||||
if (!list) return;
|
||||
var chips = list.querySelectorAll('.blog-chip');
|
||||
var cards = list.querySelectorAll('.blog-card');
|
||||
var chips = [].slice.call(list.querySelectorAll('.blog-chip'));
|
||||
var cards = [].slice.call(list.querySelectorAll('.blog-card'));
|
||||
var pager = list.querySelector('.blog-pagination');
|
||||
var numbers = pager ? pager.querySelector('.pagination-numbers') : null;
|
||||
var prevBtn = pager ? pager.querySelector('[data-nav="prev"]') : null;
|
||||
var nextBtn = pager ? pager.querySelector('[data-nav="next"]') : null;
|
||||
var pageSize = pager ? (parseInt(pager.getAttribute('data-page-size'), 10) || 6) : 6;
|
||||
|
||||
function apply(topic) {
|
||||
cards.forEach(function (card) {
|
||||
var show = topic === 'all' || card.getAttribute('data-topic') === topic;
|
||||
card.hidden = !show;
|
||||
var state = { topic: 'all', page: 1 };
|
||||
|
||||
function matching() {
|
||||
return cards.filter(function (c) {
|
||||
return state.topic === 'all' || c.getAttribute('data-topic') === state.topic;
|
||||
});
|
||||
}
|
||||
|
||||
// Compact list of page tokens: numbers and 'dots'.
|
||||
function tokens(total, cur) {
|
||||
if (total <= 7) {
|
||||
var all = [];
|
||||
for (var i = 1; i <= total; i++) all.push(i);
|
||||
return all;
|
||||
}
|
||||
var set = { 1: 1, 2: 1 };
|
||||
set[total] = 1; set[total - 1] = 1;
|
||||
set[cur] = 1; set[cur - 1] = 1; set[cur + 1] = 1;
|
||||
var pages = Object.keys(set).map(Number).filter(function (n) { return n >= 1 && n <= total; }).sort(function (a, b) { return a - b; });
|
||||
var out = [];
|
||||
for (var j = 0; j < pages.length; j++) {
|
||||
if (j > 0 && pages[j] - pages[j - 1] > 1) out.push('dots');
|
||||
out.push(pages[j]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function buildPager(total) {
|
||||
if (!pager) return;
|
||||
if (total <= 1) { pager.hidden = true; return; }
|
||||
pager.hidden = false;
|
||||
numbers.innerHTML = '';
|
||||
tokens(total, state.page).forEach(function (t) {
|
||||
if (t === 'dots') {
|
||||
var s = document.createElement('span');
|
||||
s.className = 'page-dots';
|
||||
s.textContent = '...';
|
||||
numbers.appendChild(s);
|
||||
return;
|
||||
}
|
||||
var b = document.createElement('button');
|
||||
b.type = 'button';
|
||||
b.className = 'page-number' + (t === state.page ? ' active' : '');
|
||||
b.textContent = t;
|
||||
b.addEventListener('click', function () { state.page = t; render(true); });
|
||||
numbers.appendChild(b);
|
||||
});
|
||||
prevBtn.classList.toggle('disabled', state.page <= 1);
|
||||
nextBtn.classList.toggle('disabled', state.page >= total);
|
||||
}
|
||||
|
||||
function render(scroll) {
|
||||
var m = matching();
|
||||
var total = Math.max(1, Math.ceil(m.length / pageSize));
|
||||
if (state.page > total) state.page = total;
|
||||
if (state.page < 1) state.page = 1;
|
||||
var start = (state.page - 1) * pageSize;
|
||||
var end = start + pageSize;
|
||||
cards.forEach(function (c) { c.hidden = true; });
|
||||
m.slice(start, end).forEach(function (c) { c.hidden = false; });
|
||||
buildPager(total);
|
||||
if (scroll) list.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
|
||||
chips.forEach(function (chip) {
|
||||
chip.addEventListener('click', function () {
|
||||
chips.forEach(function (c) { c.classList.remove('is-active'); });
|
||||
chip.classList.add('is-active');
|
||||
apply(chip.getAttribute('data-topic'));
|
||||
state.topic = chip.getAttribute('data-topic');
|
||||
state.page = 1;
|
||||
render(false);
|
||||
});
|
||||
});
|
||||
if (prevBtn) prevBtn.addEventListener('click', function () { if (state.page > 1) { state.page--; render(true); } });
|
||||
if (nextBtn) nextBtn.addEventListener('click', function () { state.page++; render(true); });
|
||||
|
||||
render(false);
|
||||
})();
|
||||
Reference in new issue
Block a user