feat: portal IA per spec (home entry point, /news, /proposals+redirect, /support), live search + suggestions, article TOC, mobile disclosure menu, CMS preview styles, modernization pass 1
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
// Shared client-side news search over /search.json (no dependencies, no modules).
|
||||
// Used by the homepage hero (live suggestions) and /search (full results).
|
||||
(function () {
|
||||
window.newsSearch = function (opts) {
|
||||
const input = document.getElementById(opts.input);
|
||||
const list = document.getElementById(opts.list);
|
||||
const status = document.getElementById(opts.status);
|
||||
let index = null;
|
||||
let timer;
|
||||
async function run() {
|
||||
const q = input.value.trim().toLowerCase();
|
||||
list.innerHTML = '';
|
||||
if (q.length < 2) { status.textContent = opts.hint || ''; return; }
|
||||
if (!index) index = await (await fetch('/search.json')).json();
|
||||
const hits = index
|
||||
.filter((p) => (p.title + ' ' + p.description + ' ' + p.category).toLowerCase().includes(q))
|
||||
.slice(0, opts.limit);
|
||||
status.textContent = hits.length ? hits.length + ' ' + (opts.unit || 'result(s)') : 'No results.';
|
||||
for (const p of hits) {
|
||||
const li = document.createElement('li');
|
||||
const a = document.createElement('a');
|
||||
a.href = '/news/' + encodeURIComponent(p.slug);
|
||||
a.textContent = p.title;
|
||||
const small = document.createElement('small');
|
||||
small.textContent = p.date;
|
||||
li.append(a, small);
|
||||
list.append(li);
|
||||
}
|
||||
}
|
||||
input.addEventListener('input', () => { clearTimeout(timer); timer = setTimeout(run, 150); });
|
||||
return run; // callers may run() immediately (e.g. /search?q=…)
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user