fix: search scroll jump (atomic list swap, no clear-before-await); services grid back to 6 tiles (2 subdued planned) + planned line for the rest
This commit is contained in:
+13
-8
@@ -69,29 +69,31 @@
|
||||
// the newest articles from the same index.
|
||||
async function idle() {
|
||||
if (input.value.trim().length >= 2) return;
|
||||
list.innerHTML = '';
|
||||
// Build off-DOM, swap atomically — clearing before the await shrinks the
|
||||
// page mid-flight and the browser clamps the scroll position ("jumps up").
|
||||
const frag = document.createDocumentFragment();
|
||||
const r = recents();
|
||||
if (r.length) {
|
||||
list.append(label('Recent'));
|
||||
for (const term of r) list.append(row([term], '/search?q=' + encodeURIComponent(term), term));
|
||||
frag.append(label('Recent'));
|
||||
for (const term of r) frag.append(row([term], '/search?q=' + encodeURIComponent(term), term));
|
||||
}
|
||||
const fresh = (await ensureIndex()).slice(0, Math.max(1, 5 - r.length));
|
||||
if (input.value.trim().length >= 2) return; // typed meanwhile — run() owns the list
|
||||
list.append(label('Latest news'));
|
||||
frag.append(label('Latest news'));
|
||||
for (const p of fresh) {
|
||||
const li = row([p.title], '/news/' + encodeURIComponent(p.slug));
|
||||
const small = document.createElement('small');
|
||||
small.textContent = p.date;
|
||||
li.append(small);
|
||||
list.append(li);
|
||||
frag.append(li);
|
||||
}
|
||||
list.replaceChildren(frag);
|
||||
hint();
|
||||
status.textContent = opts.hint || (r.length ? 'Showing recent searches and latest news' : 'Showing latest news');
|
||||
}
|
||||
async function run() {
|
||||
const q = input.value.trim().toLowerCase();
|
||||
if (q.length < 2) { list.innerHTML = ''; idle(); return; }
|
||||
list.innerHTML = '';
|
||||
if (q.length < 2) { list.replaceChildren(); idle(); return; }
|
||||
const idx = await ensureIndex();
|
||||
const hits = idx
|
||||
.filter((p) => (p.title + ' ' + p.description + ' ' + p.category).toLowerCase().includes(q))
|
||||
@@ -100,13 +102,16 @@
|
||||
status.textContent = hits.length
|
||||
? hits.length + ' ' + unit + (hits.length === 1 ? '' : 's') + ' for “' + input.value.trim() + '”'
|
||||
: 'No results for “' + input.value.trim() + '” — try a shorter or different term.';
|
||||
// Off-DOM build + atomic swap (no transient page-height collapse)
|
||||
const frag = document.createDocumentFragment();
|
||||
for (const p of hits) {
|
||||
const li = row(highlight(p.title, q), '/news/' + encodeURIComponent(p.slug));
|
||||
const small = document.createElement('small');
|
||||
small.textContent = p.date;
|
||||
li.append(small);
|
||||
list.append(li);
|
||||
frag.append(li);
|
||||
}
|
||||
list.replaceChildren(frag);
|
||||
hint();
|
||||
}
|
||||
input.addEventListener('input', () => { clearTimeout(timer); timer = setTimeout(run, 150); });
|
||||
|
||||
Reference in New Issue
Block a user