Felix Riesterer: Mittels history.back() zum vorherigen Zustand des Dokuments zurück?

Liebe Mitlesende,

für unser neues Frickl suche ich nach einer eleganten Methode, mittels JavaScript den Inhalt der Seite komplett so zu ersetzen, dass ein history.back() den vorherigen Zustand wieder herstellt. Dazu gedachte ich history.pushState() zu verwenden. Jedoch lande ich mit dem Zurück-Button, der sich ja wie history.back() verhält, auf der vorherigen Seite, anstatt auf der, welche mein JavaScript umgestaltet hat. Obendrein: Die Seite lädt dann neu, was ich ja eigentlich zu vermeiden suche.

history.pushState(
  {},
  "",
  location.href.replace(/#.*/, "") + "#kitchen-sink"
);

document.title = "Ausprobieren";

document.body.innerHTML = [
  "<h1>Ausprobieren</h1>",
  "<p>...</p>"
].join("\n");

Wenn es keine reguläre Möglichkeit gibt, mein Vorhaben auf diese Weise zu realisieren, muss ich eben auf eine Art bildschirmfüllendes Modal zurückgreifen, welches durch CSS mit :target (un)sichtbar wird.

Wie bringe ich den Browser dazu, dass er sich den Zustand der Seite merkt, mir eine „neue“ Seite zugesteht, die ich mit meinem JavaScript nach Belieben gestalten kann, um dann mit dem Zurück-Button den Umbau ungeschehen machen zu können?

Liebe Grüße

Felix Riesterer

  1. Hallo Felix,

    für unser neues Frickl suche ich nach einer eleganten Methode, mittels JavaScript den Inhalt der Seite komplett so zu ersetzen, dass ein history.back() den vorherigen Zustand wieder herstellt.

    das Einzige, was mir da einfällt: Eine Identifizierung des aktuellen Zustands per Fragment Identifier.

    Jedoch lande ich mit dem Zurück-Button, der sich ja wie history.back() verhält, auf der vorherigen Seite, anstatt auf der, welche mein JavaScript umgestaltet hat. Obendrein: Die Seite lädt dann neu, was ich ja eigentlich zu vermeiden suche.

    Das ist genau das, was ich intuitiv vom Back-Button erwarten würde: Bring mich zurück zur vorherigen Seite, so wie sie vom Server geladen wurde.

    Ob eine per JS modifizierte Seite stattdessen aus dem Cache wiederhergestellt wird, ist von den individuellen Browsereinstellungen abhängig. Ebenso bei Formularen, ob die Eingaben erhalten bleiben. Ich möchte das nicht - zurück heißt zurück.

    Wie bringe ich den Browser dazu, dass er sich den Zustand der Seite merkt, mir eine „neue“ Seite zugesteht, die ich mit meinem JavaScript nach Belieben gestalten kann, um dann mit dem Zurück-Button den Umbau ungeschehen machen zu können?

    Wie gesagt: Mir fällt als Ansatz nur der Fragment Identifier ein.

    Einen schönen Tag noch
     Martin

    --
    Wichtige Erkenntnis für Comiczeichner:
    Eine Sprechblase ist nicht unbedingt ein Fall für den Urologen.
  2. Hallo Felix,

    ich habe im Büro eine SPA geschrieben, die über den Fragment-Identifier unterschiedlichen Sichten darstellt. Allerdings lade ich da lediglich den HTML Rahmen vom Server und baue den Datenteil jeweils komplett mit JavaScript.

    Ich stelle es mir generell schwierig vor, per History-API zwischen einer servergenerierten und scriptgenerierten Seite hin und her zu wechseln. Vor allem muss es ja auch gelingen, die Frickl-Ansicht zu bookmarken. Wenn du das DOM, das vom Server kam, komplett ersetzt und dann bei back() lediglich das Fragment austauschst, lädt der Browser nichts vom Server.

    Ich muss mir das erst nochmal in Ruhe anschauen, meine SPA ist schon ein paar Jahre her.

    Rolf

    --
    sumpsi - posui - obstruxi
  3. Hallo Felix,

    das ist alles nicht so einfach. Wenn Du auf einer Seite bleibst und den Hash änderst (durch Tippen oder durch einen Hash-Link), dann bekommst Du popstate-Events. Aber der Browser ändert das DOM nicht.

    Einfach nur pushState aufrufen tut auch nichts. Du kannst damit eine neue URL in die History legen, aber weiter passiert nichts.

    Wenn Du hingegen einen Link auf #frickl:Super01.html anklickst (oder dies an location zuweist), dann wird die Adresse auf den History-Stack gelegt UND du bekommst ein popstate-Event.

    Wenn Du auf /wiki/TolleBeispiele#frickl:Super01.html bist, von dort zu forum.selfhtml.org wechselst und dann mit dem BACK Button zurückkehrst, bekommst Du ebenfalls ein popstate-Event.

    Einziger Wermutstropfen: Wenn du im Forum bist und dort einem Link auf /wiki/TolleBeispiele#frickl:Super01.html folgst, dann bekommst Du kein popstate-Event. Eine Frickl-URL als Lesezeichen muss man anders behandeln.

    Die Aufgabe "Frickl initialisieren" lagert man deshalb am besten in eine Funktion aus. Die prüft, ob ein #frickl-Hash da ist. Wenn nein, endet sie gleich wieder. Wenn ja, baut sie das Frickl auf.

    Diese Funktion rufst Du auf

    • im popstate Event
    • EVENTUELL nach dem pushState-Funktionsaufruf - ich meine aber, das ist unnötig, ein Link tut's genauso
    • beim Laden der Seite mit einem #frickl Hash.

    Für den Fall, dass Du von einer #frickl-URL auf die "Normalversion" der Seite zurückwillst, musst Du die Seite neu laden. Es dürfte unmöglich sein, einen Snapshot der Seite zu machen, während Du das Frickl anzeigst. Hier gibt es übrigens einen wichtigen Unterschied: Wechselst Du von /foo#frickl nach /foo#, gibt es ein popstate Event. Wechselst Du aber von /foo#frickl nach /foo, gibt's das nicht, statt dessen lädt der Browser die Seite neu!

    Die bessere Alternative könnte sein, Frickl als modalen Fullscreen-Dialog über den Artikel zu legen. Wenn ein popstate kommt, kein #frickl im Hash steht und der Dialog geöffnet ist, machst Du ihn einfach zu.

    Hier ist mein Spielzeug dazu

    Dieser Link öffnet sofort die Frickl-Ansicht

    Jedoch lande ich mit dem Zurück-Button, der sich ja wie history.back() verhält, auf der vorherigen Seite, anstatt auf der, welche mein JavaScript umgestaltet hat.

    Das kann ich nicht nachvollziehen, vielleicht müssen wir dafür mal eine Discord-Session machen.

    Rolf

    --
    sumpsi - posui - obstruxi