-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfilter.js
More file actions
69 lines (59 loc) · 2.28 KB
/
Copy pathfilter.js
File metadata and controls
69 lines (59 loc) · 2.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Client-side gallery filtering. Pure DOM: reads data-* attributes off the
// pre-rendered cards and toggles [hidden]. No framework, no search index.
// The grid renders fully server-side, so it still works with JS disabled;
// this only adds interactivity on top.
const q = document.getElementById('q');
const dept = document.getElementById('dept');
const type = document.getElementById('type');
const cards = [...document.querySelectorAll('.row')];
const tagButtons = [...document.querySelectorAll('.tag-toggle')];
const resultLine = document.getElementById('result-line');
const srStatus = document.getElementById('sr-status');
const empty = document.getElementById('empty');
const activeTags = new Set();
function apply() {
const term = (q?.value || '').trim().toLowerCase();
const d = dept?.value || '';
const t = type?.value || '';
let shown = 0;
for (const card of cards) {
const cardTags = (card.dataset.tags || '').split('|').filter(Boolean);
const matches =
(!term || card.dataset.search.includes(term)) &&
(!d || card.dataset.department === d) &&
(!t || card.dataset.type === t) &&
// OR within tags: match if the card carries any selected tag
(activeTags.size === 0 || cardTags.some((tag) => activeTags.has(tag)));
card.hidden = !matches;
if (matches) shown++;
}
if (resultLine) {
resultLine.textContent = `${shown} of ${cards.length} shown`;
}
if (srStatus) {
srStatus.textContent = shown === 0 ? 'No entries match those filters.' : `${shown} of ${cards.length} entries shown.`;
}
if (empty) empty.hidden = shown !== 0;
}
q?.addEventListener('input', apply);
dept?.addEventListener('change', apply);
type?.addEventListener('change', apply);
document.getElementById('clear-filters')?.addEventListener('click', () => {
if (q) q.value = '';
if (dept) dept.value = '';
if (type) type.value = '';
activeTags.clear();
for (const btn of tagButtons) btn.setAttribute('aria-pressed', 'false');
apply();
});
for (const btn of tagButtons) {
btn.addEventListener('click', () => {
const tag = btn.dataset.tag;
const pressed = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', String(!pressed));
if (pressed) activeTags.delete(tag);
else activeTags.add(tag);
apply();
});
}
apply();