Dashboard fror bei gecachter alter HTML ein - neue Elemente jetzt null-sicher
User: "ich sehe die Aenderungen nicht im dashboard". Server war korrekt:
v=129 samt #hdr-hl ausgeliefert, Cache-Control: no-store gesetzt, kein
Service-Worker, hl_live im Snapshot vorhanden.
Ursache: index.html und app.js werden vom Browser UNABHAENGIG gecacht.
Trifft neue JS auf eine alte, gecachte HTML, wirft
$("hdr-price-lbl").textContent = ... eine TypeError - und weil das mitten in
render() passiert, bricht der GESAMTE Render ab. Das Dashboard friert ein
und zeigt Altwerte, obwohl alles andere stimmt. Genau das Symptom.
Fix: neue Elemente ueber const el = $("id"); if (el) { ... } ansprechen.
Dann laeuft der Rest weiter und nur das neue Feld fehlt, bis die HTML
nachgeladen ist. Betrifft hdr-price-lbl und hdr-hl.
Regel in CLAUDE.md aufgenommen - das ?v=N-Bump bustet nur app.js/style.css,
NICHT die index.html selbst.
v=130.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7427c36922
commit
2ea17ce3e0
@@ -153,6 +153,18 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
|
|||||||
```
|
```
|
||||||
Gegenprobe nach jedem Kompilieren: `#property version` im Terminal-`.mq5` **und**
|
Gegenprobe nach jedem Kompilieren: `#property version` im Terminal-`.mq5` **und**
|
||||||
der Zeitstempel der `.ex5` müssen zum erwarteten Stand passen.
|
der Zeitstempel der `.ex5` müssen zum erwarteten Stand passen.
|
||||||
|
- **⚠ 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 = …`)
|
||||||
|
eine TypeError — und weil das mitten in `render()` passiert, bricht der **GESAMTE
|
||||||
|
Render** ab: das Dashboard friert ein und zeigt Altwerte, obwohl Server und Snapshot
|
||||||
|
korrekt sind. Real passiert beim HL-Kurs-Einbau (User: „ich sehe die Änderungen
|
||||||
|
nicht"); Server lieferte nachweislich v=129 samt `#hdr-hl` aus, `Cache-Control:
|
||||||
|
no-store` war gesetzt, kein Service-Worker — die Ursache lag allein in dieser
|
||||||
|
Kombination. **Regel:** neue Elemente per `const el = $("id"); if (el) { … }`
|
||||||
|
ansprechen, dann läuft der Rest weiter und nur das neue Feld fehlt, bis die HTML
|
||||||
|
nachgeladen ist. (Das `?v=N`-Bump bustet nur `app.js`/`style.css` — NICHT die
|
||||||
|
`index.html` selbst.)
|
||||||
- **Web-Assets:** Browser cacht hart → in `web/index.html` `?v=N` **hochzählen**
|
- **Web-Assets:** Browser cacht hart → in `web/index.html` `?v=N` **hochzählen**
|
||||||
bei jeder JS/CSS-Änderung; Server sendet `Cache-Control: no-store`. Hängt der
|
bei jeder JS/CSS-Änderung; Server sendet `Cache-Control: no-store`. Hängt der
|
||||||
Handy-Cache: Inkognito oder Seite mit frischem `?xN` öffnen.
|
Handy-Cache: Inkognito oder Seite mit frischem `?xN` öffnen.
|
||||||
@@ -2131,7 +2143,7 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
|
|||||||
Signal → **Hinweis-Dialog „trotzdem eröffnen?"** (überschreibbar). CLOSE bei
|
Signal → **Hinweis-Dialog „trotzdem eröffnen?"** (überschreibbar). CLOSE bei
|
||||||
**negativem** P&L → Sicherheitsabfrage; im Plus/Breakeven direkt. Sonst keine
|
**negativem** P&L → Sicherheitsabfrage; im Plus/Breakeven direkt. Sonst keine
|
||||||
Token-Dialoge (`require_token=false`). Audio braucht 1× Nutzer-Tap.
|
Token-Dialoge (`require_token=false`). Audio braucht 1× Nutzer-Tap.
|
||||||
- Asset-Version aktuell **v=126** (in `web/index.html` hochzählen, siehe Workflows).
|
- Asset-Version aktuell **v=130** (in `web/index.html` hochzählen, siehe Workflows).
|
||||||
Schriftgrößen 2026-07-24 global **+4px** (2× je +2px auf User-Wunsch; Body-Basis
|
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
|
14→18px). ⚠ Betrifft in `style.css` sowohl `font-size:Npx` (71×) ALS AUCH die
|
||||||
`font:<weight> Npx/…`-**Shorthand** (3×: `.ms-chip`/`.ms-bos-lbl`/`.sqm-badge` —
|
`font:<weight> Npx/…`-**Shorthand** (3×: `.ms-chip`/`.ms-bos-lbl`/`.sqm-badge` —
|
||||||
|
|||||||
+14
-4
@@ -482,15 +482,25 @@ function render(d) {
|
|||||||
// stillen Vertauschung).
|
// stillen Vertauschung).
|
||||||
$("hdr-price").textContent = m.bid != null ? fmt(m.bid) : "—";
|
$("hdr-price").textContent = m.bid != null ? fmt(m.bid) : "—";
|
||||||
$("hdr-price").className = priceCls;
|
$("hdr-price").className = priceCls;
|
||||||
$("hdr-price-lbl").textContent = d.market_closed ? "KURS · ZU" : "KURS";
|
// ⚠ NULL-SICHER auf NEUE Elemente zugreifen (Fix 2026-08-01): `index.html` und
|
||||||
$("hdr-price-lbl").title = d.market_closed
|
// `app.js` werden vom Browser UNABHÄNGIG gecacht. Trifft neue JS auf eine alte,
|
||||||
|
// gecachte HTML, wirft ein direkter Zugriff auf ein noch nicht existierendes
|
||||||
|
// Element eine TypeError — und weil das mitten in `render()` passiert, bricht der
|
||||||
|
// GESAMTE Render ab: das Dashboard friert ein und zeigt Altwerte. Genau so sah der
|
||||||
|
// Fehler beim Nutzer aus („ich sehe die Änderungen nicht"). Mit Guard läuft der
|
||||||
|
// Rest normal weiter, nur die neuen Felder fehlen, bis die HTML nachgeladen ist.
|
||||||
|
const lblEl = $("hdr-price-lbl");
|
||||||
|
if (lblEl) {
|
||||||
|
lblEl.textContent = d.market_closed ? "KURS · ZU" : "KURS";
|
||||||
|
lblEl.title = d.market_closed
|
||||||
? `Pepperstone geschlossen — letzter Tick vor ${Math.round((d.tick_age_s || 0) / 60)} min`
|
? `Pepperstone geschlossen — letzter Tick vor ${Math.round((d.tick_age_s || 0) / 60)} min`
|
||||||
: "";
|
: "";
|
||||||
|
}
|
||||||
|
|
||||||
// Hyperliquid daneben: basis-korrigiert (= MT5-Niveau), mit Abweichung im Tooltip.
|
// Hyperliquid daneben: basis-korrigiert (= MT5-Niveau), mit Abweichung im Tooltip.
|
||||||
const hl = d.hl_live || null;
|
const hl = d.hl_live || null;
|
||||||
const hlEl = $("hdr-hl");
|
const hlEl = $("hdr-hl");
|
||||||
if (hl && hl.mid_mt5 != null) {
|
if (hlEl && hl && hl.mid_mt5 != null) {
|
||||||
const arr = hl.trend === "up" ? "▲" : hl.trend === "down" ? "▼" : "";
|
const arr = hl.trend === "up" ? "▲" : hl.trend === "down" ? "▼" : "";
|
||||||
hlEl.textContent = fmt(hl.mid_mt5) + (arr ? " " + arr : "");
|
hlEl.textContent = fmt(hl.mid_mt5) + (arr ? " " + arr : "");
|
||||||
const dv = hl.vs_mt5;
|
const dv = hl.vs_mt5;
|
||||||
@@ -500,7 +510,7 @@ function render(d) {
|
|||||||
+ `${hl.basis >= 0 ? "+" : ""}${fmt(hl.basis, 3)} = ${fmt(hl.mid_mt5)} · `
|
+ `${hl.basis >= 0 ? "+" : ""}${fmt(hl.basis, 3)} = ${fmt(hl.mid_mt5)} · `
|
||||||
+ `${fmt(hl.age_s, 0)} s alt`
|
+ `${fmt(hl.age_s, 0)} s alt`
|
||||||
+ (dv != null ? ` · ggü. Broker ${dv >= 0 ? "+" : ""}${fmt(dv, 3)}` : "");
|
+ (dv != null ? ` · ggü. Broker ${dv >= 0 ? "+" : ""}${fmt(dv, 3)}` : "");
|
||||||
} else {
|
} else if (hlEl) {
|
||||||
hlEl.textContent = "—"; hlEl.className = ""; hlEl.title = "";
|
hlEl.textContent = "—"; hlEl.className = ""; hlEl.title = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@
|
|||||||
<meta name="theme-color" content="#0d1117">
|
<meta name="theme-color" content="#0d1117">
|
||||||
<title>Oil · MT5</title>
|
<title>Oil · MT5</title>
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
<link rel="stylesheet" href="style.css?v=129">
|
<link rel="stylesheet" href="style.css?v=130">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- Modul-Menü (ganz oben) -->
|
<!-- Modul-Menü (ganz oben) -->
|
||||||
@@ -248,6 +248,6 @@
|
|||||||
<div id="toast" class="toast hidden"></div>
|
<div id="toast" class="toast hidden"></div>
|
||||||
|
|
||||||
<script src="lightweight-charts.standalone.production.js?v=114"></script>
|
<script src="lightweight-charts.standalone.production.js?v=114"></script>
|
||||||
<script src="app.js?v=129"></script>
|
<script src="app.js?v=130"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user