From 3e8fa9fea87692695c9357276a691ee41dc13327 Mon Sep 17 00:00:00 2001 From: Axel Hocks Date: Fri, 7 Aug 2026 07:34:01 +0200 Subject: [PATCH] Auffang-Element in app.js: ein fehlendes Element bricht nicht mehr den Render Gemessen: 95 direkte $("id")-Zugriffe, 0 davon abgesichert - obwohl die Regel "neue Elemente per const el = $(..); if (el) {..}" seit 01.08. in CLAUDE.md steht. Eine Regel mit 0 Prozent Befolgung ist keine Regel, also loest es jetzt der Code an EINER Stelle statt an 95. $() gibt bei fehlendem Element ein detachiertes zurueck statt null, plus einmalige console.warn je ID (kein stiller Fallback - das war der catch{}-Fehler in pollSnapshot). ?. war NICHT die Loesung: 80 der 95 Zugriffe sind Zuweisungen, und $("x")?.y = v ist ein Syntaxfehler. $streng() ist der wichtige Teil. Alle Eingabefelder sind type="number", und leer heisst dort ausdruecklich "Stop entfernen" (sl: null). Mit dem Auffang-Element waere .value undefined -> parseFloat NaN -> JSON.stringify macht daraus wieder null: eine fehlende Eingabemaske haette den Broker-SL einer laufenden Position stillschweigend geloescht. Betroffen war genau eine Funktion (sendSltp); setSrMin/setEmg/setManualMargin/setMarginPct fangen NaN bereits ab (geprueft, nicht angenommen). Beide Richtungen an einem Minimal-DOM verifiziert, das eine alte index.html simuliert: mit der alten $-Definition bricht der Render beim ZWEITEN Feld ab, mit der neuen laeuft er durch. Der Order-Pfad bricht in beiden Faellen sauber ab. Asset-Version v=149 -> v=150. Co-Authored-By: Claude Opus 5 --- CLAUDE.md | 36 ++++++++++++++++++++++++++++++++- web/app.js | 54 +++++++++++++++++++++++++++++++++++++++++++++++--- web/index.html | 4 ++-- 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 3de7966..11c9bc4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -226,6 +226,40 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche: ``` Gegenprobe nach jedem Kompilieren: `#property version` im Terminal-`.mq5` **und** der Zeitstempel der `.ex5` müssen zum erwarteten Stand passen. +- **✅⚠ AUFFANG-ELEMENT statt Disziplin (Fix 2026-08-07, v=150) — die Regel + direkt darunter wird jetzt vom CODE durchgesetzt.** `$()` gibt bei fehlendem + Element nicht mehr `null` zurück, sondern ein **detachiertes ``**: + ```js + const _FEHLT = document.createElement("span"); + const $ = (id) => document.getElementById(id) || _FEHLT; // + 1× console.warn je ID + const $streng = (id) => document.getElementById(id); // gibt null + ``` + ⚠⚠ **Anlass ist eine Messung, kein Gefühl: die Regel „neue Elemente per + `const el = $(…); if (el) {…}`" war bei 0 von 95 direkten Zugriffen befolgt.** + 95 Stellen, an denen ein fehlendes Element den **GESAMTEN** Render abbricht; + 0 davon abgesichert. Eine Regel mit 0 % Befolgung ist keine Regel — deshalb + löst es der Code an EINER Stelle statt an 95. + ⚠ **`?.` war NICHT die Lösung** (mein erster Vorschlag, und er war falsch): + **80 der 95** Zugriffe sind ZUWEISUNGEN, und `$("x")?.y = v` ist ein + **Syntaxfehler** — Optional Chaining ist links vom `=` verboten. + ⚠⚠ **`$streng` ist der wichtige Teil.** Alle Eingabefelder sind + `type="number"`, und **leer heißt dort ausdrücklich „Stop entfernen"** + (`sl: null`). Mit dem Auffang-Element wäre `.value` `undefined` → `parseFloat` + → NaN → `JSON.stringify` macht daraus wieder **`null`** — eine fehlende + Eingabemaske hätte den **Broker-SL einer laufenden Position stillschweigend + gelöscht.** Ein lauter Absturz ist dort das bessere Verhalten. Betroffen war + genau **eine** Funktion (`sendSltp`); `setSrMin`/`setEmg`/`setManualMargin`/ + `setMarginPct` fangen NaN bereits ab (geprüft, nicht angenommen). + ⚠ Der Fehler wird **nicht verschluckt**, sondern **1× je ID** in die Konsole + gemeldet — ein stiller Fallback wäre derselbe Fehler wie der `catch {}` in + `pollSnapshot`, der Render-Fehler lautlos gefressen hat (behoben 01.08.). + ✅ **Beide Richtungen verifiziert** an einem Minimal-DOM, das eine alte + `index.html` simuliert: mit der alten `$`-Definition bricht der Render beim + **zweiten** Feld ab, mit der neuen läuft er durch und nur die fehlenden Felder + bleiben leer; der Order-Pfad bricht in beiden Fällen sauber ab. + ⚠ Die 40 vorhandenen `if (!el) return;`-Wächter feuern jetzt nicht mehr. Sie + bleiben stehen (kein Nutzen im Entfernen, und sie greifen weiter, wenn jemand + `$streng` benutzt) — beim Lesen aber mitdenken. - **⚠ NEUE HTML-Elemente IMMER null-sicher ansprechen (Fix 2026-08-01).** `index.html` und `app.js` werden vom Browser **unabhängig** gecacht. Trifft neue JS auf eine alte, gecachte HTML, wirft ein direkter Zugriff (`$("neu").textContent = …`) @@ -4117,7 +4151,7 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche: („⚠ die Welle (steuert die Order) schweigt"). Live gegengerechnet, beide Zeilen erscheinen wie beabsichtigt. ⚠ Reine Anzeige — an Gewichten, Gates und Order-Logik ist nichts geändert. -- Asset-Version aktuell **v=149** (in `web/index.html` hochzählen, siehe Workflows). +- Asset-Version aktuell **v=150** (in `web/index.html` hochzählen, siehe Workflows). Schriftgrößen 2026-07-24 global **+4px** (2× je +2px auf User-Wunsch; Body-Basis 14→18px). ⚠ Betrifft in `style.css` sowohl `font-size:Npx` (71×) ALS AUCH die `font: Npx/…`-**Shorthand** (3×: `.ms-chip`/`.ms-bos-lbl`/`.sqm-badge` — diff --git a/web/app.js b/web/app.js index 4239181..2d68a35 100644 --- a/web/app.js +++ b/web/app.js @@ -1,6 +1,44 @@ "use strict"; // ── Live-Anbindung an server.py via WebSocket (Fallback: Polling) ────────── -const $ = (id) => document.getElementById(id); + +// ⚠⚠ AUFFANG-ELEMENT (2026-08-07) — behebt die haeufigste Ausfallart des +// Dashboards. `index.html` und `app.js` werden vom Browser UNABHAENGIG +// gecacht; trifft neue JS auf alte HTML, war `$("neu").textContent = …` eine +// TypeError — und weil das mitten in `render()` passiert, brach der GESAMTE +// Render ab: das Dashboard fror auf Altwerten ein, obwohl Server und Snapshot +// korrekt waren. Real passiert beim HL-Kurs-Einbau (01.08.), beinahe erneut +// beim Entfernen der Setup-Zeile (06.08., 8 Folgezugriffe auf `w`). +// Die Gegenregel „neue Elemente per `const el = $(…); if (el) {…}`" stand seit +// 01.08. in CLAUDE.md — GEMESSEN befolgt wurde sie bei **0 von 95** direkten +// Zugriffen. Eine Regel mit 0 % Befolgung ist keine Regel, also loest es jetzt +// der Code an EINER Stelle statt an 95. +// ⚠ `?.` waere hier keine Loesung gewesen: **80 der 95** Zugriffe sind +// ZUWEISUNGEN, und `$("x")?.y = v` ist ein Syntaxfehler (Optional Chaining ist +// links vom `=` verboten). +// ⚠ Der Fehler wird NICHT verschluckt, sondern EINMAL je ID in die Konsole +// gemeldet — ein stiller Fallback waere derselbe Fehler wie der `catch {}` in +// `pollSnapshot`, der Render-Fehler lautlos gefressen hat (behoben 01.08.). +const _FEHLT = document.createElement("span"); +const _fehlendGemeldet = new Set(); +const $ = (id) => { + const el = document.getElementById(id); + if (el) return el; + if (!_fehlendGemeldet.has(id)) { + _fehlendGemeldet.add(id); + console.warn(`[app] Element #${id} fehlt — vermutlich alte index.html im ` + + `Cache. Schreibzugriffe laufen ins Leere, der Rest rendert ` + + `weiter. Abhilfe: ?v=N in index.html hochzaehlen.`); + } + return _FEHLT; +}; + +// ⚠ STRENGE Variante — gibt `null` zurueck, wenn das Element fehlt. +// Zwingend fuer Pfade, die einen gelesenen Wert an den BROKER schicken: dort +// ist „Feld fehlt" NICHT dasselbe wie „Feld ist leer". Beim SL/TP-Feld heisst +// leer ausdruecklich „Stop entfernen" — ein Auffang-Element wuerde daraus ein +// stilles Loeschen des Broker-SL einer laufenden Position machen. Ein lauter +// Absturz ist dort das bessere Verhalten als ein stiller Schaden. +const $streng = (id) => document.getElementById(id); function fmt(v, d = 3) { return (v === null || v === undefined || isNaN(v)) ? "—" : Number(v).toFixed(d); @@ -1359,10 +1397,20 @@ document.querySelectorAll(".btn[data-side]").forEach(btn => { // Manuelles SL/TP (Trade-Bereich) — sendet beide Felder; deaktiviert das Trailing. async function sendSltp() { - const slv = $("tb-sl").value, tpv = $("tb-tp").value; + // ⚠ STRENG (s. `$streng` oben): hier ist „Feld fehlt" NICHT „Feld ist leer". + // Leer heisst ausdruecklich „Stop entfernen" (`sl: null`) — mit dem + // Auffang-Element waere `.value` `undefined`, `parseFloat` liefert NaN, und + // `JSON.stringify` macht daraus wieder `null`. Eine fehlende Eingabemaske + // wuerde so den Broker-SL einer laufenden Position stillschweigend loeschen. + const elSl = $streng("tb-sl"), elTp = $streng("tb-tp"); + if (!elSl || !elTp) { + toast("SL/TP-Felder nicht geladen — Seite neu laden (Strg+F5)", false); + return; + } + const slv = elSl.value, tpv = elTp.value; const tok = await ensureToken(); if (tok === null) return; - $("tb-sl").blur(); $("tb-tp").blur(); + elSl.blur(); elTp.blur(); try { const r = await fetch("api/sltp", { method: "POST", headers: { "X-Auth-Token": tok, "Content-Type": "application/json" }, diff --git a/web/index.html b/web/index.html index e509cc2..68b6b9a 100644 --- a/web/index.html +++ b/web/index.html @@ -6,7 +6,7 @@ Oil · MT5 - + @@ -330,6 +330,6 @@ - +