Die Stelle bleibt -- auch wenn die Seite dazwischen neu laedt

Filipe, zum vierten Mal: "wenn ich in eine kategorie rein gehe und dan
zurueck geh die hauptseite immer wieder ganz hoch ... ohne dass die
seite hoch scrollt ODER NEU LAEDT."

DAS "ODER NEU LAEDT" WAR DER HINWEIS, und ich habe ihn zweimal
ueberlesen. kopf.js laedt die Seite selbst neu, sobald der Browser sie
aus seinem Rueckwaerts-Speicher holt -- damit keine veralteten Zahlen
dastehen. Nach einem Neuladen heisst die Navigationsart aber "reload",
nicht "back_forward".

UND DIE EIGENTLICHE BOSHEIT stand in einer Zeile, die ich selbst
geschrieben habe: Wurde eine Ankunft nicht als Zurueck erkannt, wurde
die gemerkte Stelle GELOESCHT. Ein einziges Neuladen reichte -- danach
half auch das naechste Zurueckgehen nicht mehr. Deshalb "geht es immer
noch nicht", obwohl ich es dreimal fuer behoben hielt.

WARUM ES IN JEDER MESSUNG FUNKTIONIERT HAT: kopf.js haelt einen
Ereignisstrom offen, und der sperrt den Rueckwaerts-Speicher aus.
`persisted` bleibt hier immer false, die Neulade-Zeile lief nie. Auf
einem echten Handy greift er sehr wohl. Man muss den Weg gehen, den der
Mensch geht -- und wenn man ihn nicht nachstellen kann, baut man gegen
ALLE Wege robust statt gegen einen.

FUENF AENDERUNGEN:

  Die Stelle wird LAUFEND gemerkt (gedrosselt auf 250 ms), nicht nur
  beim Klicken und Verlassen. Deckt auch die Glocke, eine
  Benachrichtigung und einen Absturz des Reiters ab.

  Nichts wird mehr geloescht. Die Stelle verfaellt von selbst nach
  einer Stunde.

  Wiederhergestellt wird jetzt auch bei "reload" und bei "navigate mit
  Herkunft aus diesem Haus" -- nicht nur bei "back_forward".

  Vor dem Neuladen aus dem Rueckwaerts-Speicher wird die Stelle samt
  Merker festgehalten.

  Der Pfeil in der Kopfleiste setzt den Merker jetzt fuer BEIDE seiner
  Wege. Er nimmt history.back() nur, wenn `document.referrer` da ist --
  sonst location.assign(), und das ist fuer den Browser ein Hingehen.
  Hier stand "der braucht nichts"; fuer den zweiten Weg stimmte das nie.

Ein Neuanfang faengt weiterhin oben an: keine Herkunft, kein Merker --
also vom Startbildschirm, aus einer Benachrichtigung, ueber die
Adresszeile.

Beim Bauen fast hineingelaufen: `START` steht in einem anderen Block
derselben Datei und waere an der neuen Stelle ein Absturz gewesen --
dieselbe Falle wie bei `$` am 21.09. Jetzt gibt der erste Block ihn
einmal bekannt, statt ihn abzuschreiben.

Geprueft: pruef-stelle 15/0 (war 9) -- Brotkrume (navigate),
Browser-Zurueck (back_forward), NEULADEN (reload), Neuanfang oben, und
dass eine fremde Ankunft die Stelle nicht wegwirft. Dazu pruef-sprung
43/0, pruef-start-ansicht 153/0, pruef-css-klassen 30/0.
This commit is contained in:
2026-09-22 00:54:28 +02:00
parent 66789aabcd
commit 2b6c2be1ad
40 changed files with 725 additions and 531 deletions
+131 -10
View File
@@ -9,6 +9,11 @@
'use strict';
const START = '/workspace/start.html';
/* WEITER UNTEN GEBRAUCHT, IN EINEM ANDEREN BLOCK. Diese Datei hat
mehrere getrennte Bloecke; `START` ist hier eingeschlossen und
waere dort ein Absturz. Abschreiben waere die zweite Stelle, die
beim naechsten Umbau vergessen wird -- also einmal bekannt geben. */
window.__startSeite = START;
/* ---------- Wer angemeldet ist -------------------------------------------
@@ -1942,7 +1947,29 @@
Nur im ersten Fall wird neu geladen -- ein pauschales Neuladen bei
jedem Anzeigen wäre eine Endlosschleife. */
addEventListener('pageshow', (e) => {
if (e.persisted) location.reload();
if (!e.persisted) return;
/* DIE STELLE UEBERLEBT DAS NEULADEN (21.09.2026).
----------------------------------------------------------------
Filipe, zum vierten Mal: "wenn ich in eine kategorie rein gehe
und dan zurueck geh die hauptseite immer wieder ganz hoch ...
ohne dass die seite hoch scrollt ODER NEU LAEDT."
Das "oder neu laedt" war der entscheidende Hinweis, und ich habe
ihn zweimal ueberlesen. Genau hier wird neu geladen -- und nach
einem Neuladen heisst die Navigationsart "reload", nicht
"back_forward". Die Wiederherstellung sprang deshalb nicht an
UND loeschte die gemerkte Stelle sogar (siehe unten). Ein
einziges Zurueckgehen reichte, und danach war sie fuer immer weg.
Warum es in JEDER Messung funktionierte: Hier haelt kopf.js
einen Ereignisstrom offen, und der sperrt den Rueckwaerts-
Speicher aus -- `persisted` blieb immer false, diese Zeile lief
nie. Auf einem echten Handy greift er sehr wohl.
Jetzt wird die Stelle samt Zurueck-Merker festgehalten, BEVOR
neu geladen wird. Danach findet die Wiederherstellung sie wieder. */
if (typeof window.stelleFesthalten === 'function') window.stelleFesthalten();
location.reload();
});
})();
@@ -2005,8 +2032,14 @@
/* Nach so vielen Millisekunden wird nicht mehr versucht. Drei
Sekunden sind großzügig für einen Abruf und kurz genug, dass es
nie nach „die Seite hängt" aussieht. */
var FRIST_MS = 3000;
nie nach „die Seite hängt" aussieht.
AUF SECHS ERHOEHT (21.09.2026). Drei Sekunden sind hier am Kabel
grosszuegig und auf einem Handy im Funkloch knapp -- und wer im
Funkloch ist, wartet ohnehin auf den Inhalt. Solange die Seite
nicht hoch genug ist, wird nichts gesetzt; die Frist kostet also
nichts ausser Geduld. Und wer selbst scrollt, beendet sie sofort. */
var FRIST_MS = 6000;
/* Nach einer Stunde gilt die gemerkte Stelle nicht mehr. */
var ALTER_MS = 3600000;
/* Unter dieser Höhe lohnt das Merken nicht -- wer zehn Pixel
@@ -2032,6 +2065,23 @@
dem nichts gemerkt wird. */
window.addEventListener('pagehide', merken);
window.addEventListener('beforeunload', merken);
/* UND LAUFEND, WAEHREND MAN SCROLLT (21.09.2026).
------------------------------------------------------------------
Bis heute wurde nur beim Klicken und beim Verlassen gemerkt. Das
deckt den Weg ab, den ich mir vorgestellt habe -- nicht die, die
es sonst noch gibt: die Glocke, eine Benachrichtigung, ein Skript,
das selbst weiterschickt, ein Absturz des Reiters.
Gedrosselt auf 250 ms: Ein Schreibvorgang je Bildaufbau waere
sechzigmal in der Sekunde und wuerde das Scrollen ruckeln lassen.
Bei 250 ms merkt man nichts davon, und schlimmstenfalls fehlen
die letzten 250 ms Bewegung. */
var merkUhr = 0;
window.addEventListener('scroll', function () {
if (merkUhr) return;
merkUhr = setTimeout(function () { merkUhr = 0; merken(); }, 250);
}, { passive: true });
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'hidden') merken();
});
@@ -2101,7 +2151,27 @@
&& (ziel.classList.contains('zurueck') || ziel.classList.contains('zurueck-knopf'));
if (!istZurueck) return;
var adresse = ziel.getAttribute && ziel.getAttribute('href');
if (!adresse) return; /* der Knopf nimmt history.back() -- der braucht nichts */
if (!adresse) {
/* DER PFEIL IN DER KOPFLEISTE HAT ZWEI WEGE, und nur einer davon
ist ein echtes Zurueck (21.09.2026, nachgemessen):
history.back() -> Art "back_forward", alles gut
location.assign(...) -> Art "navigate", Stelle verloren
Welcher genommen wird, entscheidet `hatVorherigeSeite()` ueber
`document.referrer`. Der fehlt schon, wenn jemand die Seite
einmal neu geladen hat. Hier stand deshalb "der braucht
nichts" -- und fuer den zweiten Weg stimmte das nie.
Der Merker wird jetzt fuer BEIDE gesetzt. Er schadet dem
ersten nicht: Kommt die Ankunft ohnehin als "back_forward"
an, wird er einfach nicht gebraucht und verfaellt. */
try {
var los = window.__startSeite || '/workspace/start.html';
zurueckMerken(new URL(los, location.href).pathname);
} catch (f) { /* egal */ }
return;
}
try {
var u = new URL(adresse, location.href);
zurueckMerken(u.pathname + u.search);
@@ -2227,16 +2297,67 @@
if (e && e.persisted) wiederherstellen();
});
if (kamVonZurueck() || ueberEigenesZurueck()) {
/* ---- Wann wird wiederhergestellt? --------------------------------
BIS HEUTE: nur bei "back_forward" und beim eigenen Merker. Alles
andere hat die gemerkte Stelle nicht nur ignoriert, sondern
GELOESCHT. Ein einziges Neuladen reichte damit, und die Stelle war
fuer immer weg -- das ist der Grund, warum Filipe es viermal
gemeldet hat und ich es viermal fuer behoben hielt.
JETZT: Wiederhergestellt wird bei jeder Ankunft, die eine
RUECKKEHR sein kann -- und das sind mehr Faelle, als ich gedacht
habe:
back_forward der Browser-Zurueck. Klar.
eigener Merker der Pfeil und die Brotkrume in der Kopfleiste.
reload neu geladen (auch das Neuladen aus dem
Rueckwaerts-Speicher). Wer eine Seite neu laedt,
will dort bleiben, wo er ist -- so macht es jeder
Browser von Haus aus.
navigate MIT von einer anderen Seite dieses Hauses hergekommen.
Herkunft Deckt den Fall ab, in dem der Pfeil
`location.assign()` nimmt.
NICHT wiederhergestellt wird bei einem echten Neuanfang: keine
Herkunft, kein Merker -- also vom Startbildschirm, aus einer
Benachrichtigung oder ueber die Adresszeile. Dort gehoert man
nach oben.
UND GELOESCHT WIRD NICHTS MEHR. Die Stelle verfaellt von selbst
nach einer Stunde (ALTER_MS). Eine Ankunft, die sie nicht braucht,
hat kein Recht, sie dem naechsten Zurueckgehen wegzunehmen. */
function kamVonAnderswo() {
if (!document.referrer) return false;
var u;
try { u = new URL(document.referrer); } catch (e) { return false; }
if (u.origin !== location.origin) return false;
if (!u.pathname.startsWith('/workspace/')) return false;
return u.pathname !== location.pathname;
}
function istNeuladen() {
try {
var e = performance.getEntriesByType('navigation')[0];
if (e && e.type) return e.type === 'reload';
return performance.navigation && performance.navigation.type === 1;
} catch (f) { return false; }
}
if (kamVonZurueck() || ueberEigenesZurueck() || istNeuladen() || kamVonAnderswo()) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', wiederherstellen);
} else {
wiederherstellen();
}
} else {
/* Ein frisch geöffneter Bereich fängt oben an -- und die alte
Stelle wird vergessen, damit sie nicht in einer halben Stunde
überraschend zuschlägt. */
try { sessionStorage.removeItem(SCHLUESSEL); } catch (e) { /* egal */ }
}
/* DAMIT DAS NEULADEN AUS DEM RUECKWAERTS-SPEICHER DIE STELLE NICHT
KOSTET -- aufgerufen weiter oben, kurz vor `location.reload()`.
Zu diesem Zeitpunkt steht die Seite noch vollstaendig da und
`window.scrollY` ist die richtige Stelle. */
window.stelleFesthalten = function () {
merken();
try { zurueckMerken(location.pathname + location.search); } catch (e) { /* egal */ }
};
})();