fix(quellen): Suche ohne <form>, Click + Enter direkt binden
Browser-Quirk: in einem <form> blieb der fetch nach Submit hängen, auch mit preventDefault() im submit-Handler. Status-Text bekam "Suche läuft …", aber die Response kam nie an — der Browser hat den fetch durch den Submit-State des Forms blockiert. Lösung: <form> → <div>, Button auf type="button". Click direkt an runSearch binden, Enter via keydown auf dem Input. Keine Form-Submit- Semantik mehr. Bei E2E-Smoketest mit Playwright reproduzierbar gefixt.
This commit is contained in:
parent
37941f0a2b
commit
e48cab6db3
@ -196,11 +196,11 @@
|
|||||||
Wortunscharf — Endungen sind egal, verwandte Begriffe werden ebenfalls
|
Wortunscharf — Endungen sind egal, verwandte Begriffe werden ebenfalls
|
||||||
gefunden.
|
gefunden.
|
||||||
</p>
|
</p>
|
||||||
<form id="quellen-search-form" class="search-box">
|
<div id="quellen-search-form" class="search-box">
|
||||||
<input type="text" id="quellen-q" name="q" placeholder="z.B. Klimaschutz, soziale Gerechtigkeit, Mietpreisbremse"
|
<input type="text" id="quellen-q" name="q" placeholder="z.B. Klimaschutz, soziale Gerechtigkeit, Mietpreisbremse"
|
||||||
autocomplete="off" minlength="2" maxlength="200">
|
autocomplete="off" minlength="2" maxlength="200">
|
||||||
<button type="submit" id="quellen-q-btn">Suchen</button>
|
<button type="button" id="quellen-q-btn">Suchen</button>
|
||||||
</form>
|
</div>
|
||||||
<div class="search-filter" style="margin-top:6px;">
|
<div class="search-filter" style="margin-top:6px;">
|
||||||
<label><input type="radio" name="qfilter" value="current" checked> nur aktuelle Programme</label>
|
<label><input type="radio" name="qfilter" value="current" checked> nur aktuelle Programme</label>
|
||||||
<label><input type="radio" name="qfilter" value="all"> auch historische</label>
|
<label><input type="radio" name="qfilter" value="all"> auch historische</label>
|
||||||
@ -318,8 +318,7 @@ function escHtml(s) {
|
|||||||
.replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
.replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runSearch(ev) {
|
async function runSearch() {
|
||||||
if (ev) ev.preventDefault();
|
|
||||||
const q = document.getElementById('quellen-q').value.trim();
|
const q = document.getElementById('quellen-q').value.trim();
|
||||||
const filter = (document.querySelector('input[name="qfilter"]:checked') || {}).value || 'current';
|
const filter = (document.querySelector('input[name="qfilter"]:checked') || {}).value || 'current';
|
||||||
const statusEl = document.getElementById('quellen-search-status');
|
const statusEl = document.getElementById('quellen-search-status');
|
||||||
@ -380,25 +379,29 @@ async function runSearch(ev) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form-Submit + Filter-Wechsel binden.
|
// Suche binden — kein <form>, sondern Click auf Button + Enter im Input.
|
||||||
// Direkt im body_scripts-Block — wenn das Script läuft, ist DOMContentLoaded
|
// Frühere <form>-Variante hatte einen Browser-Quirk: trotz preventDefault()
|
||||||
// häufig schon vorbei (Script kommt am Ende des Body). Daher kein
|
// im submit-Handler hat der anschließende fetch() nie eine Response
|
||||||
// addEventListener('DOMContentLoaded', …) als Wrapper.
|
// erhalten (Status blieb auf "Suche läuft …"). Mit einem Plain-Container +
|
||||||
|
// Button onclick funktioniert es zuverlässig.
|
||||||
//
|
//
|
||||||
// Wichtig: `runSearch` ist async und returnt Promise<false>. Das ist truthy,
|
// Direkt im body_scripts-Block — wenn das Script läuft, ist DOMContentLoaded
|
||||||
// also würde `onsubmit="return runSearch(event)"` das Default-Submit NICHT
|
// häufig schon vorbei. Daher kein addEventListener('DOMContentLoaded', …)
|
||||||
// verhindern, der fetch würde mit "Failed to fetch" abbrechen, weil die Page
|
// als Wrapper, sondern IIFE mit Idempotenz-Marker.
|
||||||
// navigiert. Stattdessen über addEventListener binden — da bleibt
|
|
||||||
// `event.preventDefault()` synchron, bevor der Promise resolvt.
|
|
||||||
(function bindQuellenSearch() {
|
(function bindQuellenSearch() {
|
||||||
const form = document.getElementById('quellen-search-form');
|
const btn = document.getElementById('quellen-q-btn');
|
||||||
if (form && !form._quellenBound) {
|
if (btn && !btn._quellenBound) {
|
||||||
form._quellenBound = true;
|
btn._quellenBound = true;
|
||||||
form.addEventListener('submit', (ev) => {
|
btn.addEventListener('click', () => runSearch());
|
||||||
ev.preventDefault();
|
}
|
||||||
// Microtask-Queue erst leeren, sonst hängt der fetch in manchen
|
const input = document.getElementById('quellen-q');
|
||||||
// Browsern beobachtbar (Submit-State blockt anschließenden fetch).
|
if (input && !input._quellenBound) {
|
||||||
setTimeout(runSearch, 0);
|
input._quellenBound = true;
|
||||||
|
input.addEventListener('keydown', (ev) => {
|
||||||
|
if (ev.key === 'Enter') {
|
||||||
|
ev.preventDefault();
|
||||||
|
runSearch();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
document.querySelectorAll('input[name="qfilter"]').forEach(r => {
|
document.querySelectorAll('input[name="qfilter"]').forEach(r => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user