From da688bb294d27d50e095c284693ba48ecddafe6d Mon Sep 17 00:00:00 2001 From: Marco Morath Date: Mon, 10 Aug 2026 11:12:34 +0200 Subject: [PATCH] Fix access categoryFiled before initialization --- tools/check-js.mjs | 11 +++++++++ web/html/js/views/list-detail.js | 40 +++++++++++++++++++------------- web/html/sw.js | 2 +- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/tools/check-js.mjs b/tools/check-js.mjs index 873ea40..d064d42 100644 --- a/tools/check-js.mjs +++ b/tools/check-js.mjs @@ -14,6 +14,17 @@ * Blockgeltungsbereiche und meldet daher nichts, was irgendwo in der * Datei deklariert ist. Für den Zweck - "ganz vergessen" statt "am * falschen Ort" - reicht das. + * + * NICHT gefunden wird deshalb der Zugriff auf ein const, das erst + * WEITER UNTEN im selben Geltungsbereich angelegt wird ("Cannot access + * 'x' before initialization"). Ein Versuch, das hier mitzuprüfen, hat + * auf sauberem Quelltext rund achtzig Fehlalarme erzeugt: Aufrufe in + * Ereignisbehandlern stehen im Text vor der Deklaration, laufen aber + * später. Zuverlässig ginge das nur mit einem echten Parser. + * + * Als Regel im Quelltext statt als Prüfung: In einem Funktionsrumpf + * erst ALLE const/let anlegen, dann die Hilfsfunktionen, dann der Code, + * der etwas tut. Dann kann der Fall nicht auftreten. */ import { readFileSync, readdirSync } from "node:fs"; diff --git a/web/html/js/views/list-detail.js b/web/html/js/views/list-detail.js index 8eaa3c4..836b569 100644 --- a/web/html/js/views/list-detail.js +++ b/web/html/js/views/list-detail.js @@ -418,6 +418,12 @@ export async function listDetailView( // Die leere Auswahl heißt bewusst "Vorgabe des Artikels" und nicht // "ohne Markt": Der Server greift in diesem Fall auf die im // Artikelstamm hinterlegte Vorgabe zurück. + // Reihenfolge in diesem Abschnitt ist wichtig: erst beide + // Auswahlfelder anlegen, dann die Hilfsfunktion, dann vorbelegen + // und einmal kennzeichnen. Ein Aufruf von markSelection() zwischen + // den beiden Deklarationen würde auf ein noch nicht angelegtes + // const zugreifen - genau das war der Fehler + // "Cannot access 'categoryField' before initialization". const marketField = markets.length ? el("select.market-select", { title: "Markt für diesen Eintrag", @@ -433,22 +439,6 @@ export async function listDetailView( markets.map((m) => el("option", { value: m.id }, m.name))) : null; - function markSelection() { - // Leeres Attribut = keine Vorgabe; das Stylesheet hebt eine - // getroffene Auswahl hervor. - for (const field of [marketField, categoryField]) { - if (!field) continue; - if (field.value) field.removeAttribute("data-empty"); - else field.setAttribute("data-empty", ""); - } - } - - if (marketField && lastMarket - && markets.some((m) => m.id === lastMarket)) { - marketField.value = lastMarket; - } - markSelection(); - const categoryField = categories.length ? el("select.category-select", { title: "Warengruppe für diesen Eintrag", @@ -462,10 +452,28 @@ export async function listDetailView( categories.map((c) => el("option", { value: c.id }, c.name))) : null; + function markSelection() { + // Leeres Attribut = keine Vorgabe; das Stylesheet hebt eine + // getroffene Auswahl hervor. + for (const field of [marketField, categoryField]) { + if (!field) continue; + if (field.value) field.removeAttribute("data-empty"); + else field.setAttribute("data-empty", ""); + } + } + + // Zuletzt getroffene Auswahl wiederherstellen - aber nur, wenn es + // den Eintrag noch gibt. Ein gelöschter Markt darf nicht dazu + // führen, dass das Feld leer aussieht und trotzdem einen Wert hat. + if (marketField && lastMarket + && markets.some((m) => m.id === lastMarket)) { + marketField.value = lastMarket; + } if (categoryField && lastCategory && categories.some((c) => c.id === lastCategory)) { categoryField.value = lastCategory; } + markSelection(); const suggestionBox = el("ul.suggestions", { hidden: true }); diff --git a/web/html/sw.js b/web/html/sw.js index 941b659..d22e776 100644 --- a/web/html/sw.js +++ b/web/html/sw.js @@ -5,7 +5,7 @@ // Bei jeder Änderung an den Dateien unten hochzählen. Der Wert entscheidet, // wann alte Zwischenspeicher verworfen werden. -const VERSION = "v31"; +const VERSION = "v32"; const SHELL_CACHE = `einkaufsapp-shell-${VERSION}`; const SHELL = [