2015-01-19 7 views
23

Mit der html5 window.history API kann ich die Navigation in meiner Web App ziemlich gut steuern. Die App hat derzeit zwei Zustände: selectDate (1) und enterDetails (2).JS - window.history - Löschen eines Status

, wenn die Anwendung geladen wird, I replaceState und einen popState Zuhörers eingestellt:

history.replaceState({stage:"selectDate",...},...); 
window.onpopstate = function(event) { 
    that.toStage(event.state.stage); 
}; 

wenn ein Datum ausgewählt wird, und die Anwendung bewegt sich 2 Stufe I Zustand schieben 2 auf den Stapel:

history.pushState({stage:"enterDetails",...},...); 

Dieser Status wird immer dann geändert, wenn sich Details ändern, sodass sie im Verlauf gespeichert werden.

Es gibt drei Möglichkeiten der Stufe 2 zu verlassen:

  • save (Ajax abschicken)
  • abbrechen
  • Zurück-Taste

Die Zurück-Taste durch die popstate Zuhörer behandelt wird. Die Abbrechen-Taste schiebt Stufe 1, so dass der Benutzer zurück zu den Details gehen kann, die sie die Zurück-Taste eingegeben haben. Beide funktionieren gut.

Die Schaltfläche "Speichern" sollte wieder auf Stufe 1 zurückgesetzt werden und es dem Benutzer nicht erlauben, zurück zur Detailseite zu navigieren (da sie bereits eingereicht wurden). Basisch, y sollte der Historienstapel länge = 1 sein.

Aber es scheint kein history.delete() oder history.merge() zu sein. Das Beste, was ich tun kann, ist ein history.replaceState(stage1), der den Geschichtestapel wie folgt lässt: ["selectDate","selectDate"].

Wie kann ich eine Schicht loswerden?

Edit:

Gedanke an etwas anderes, aber es funktioniert auch nicht.

history.back(); //moves history to the correct position 
location.href = "#foo"; // successfully removes ability to go 'forward', 
         // but also adds another layer to the history stack 

Dies lässt den Verlaufsstapel als ["selectDate","selectDate#foo"].

Gibt es also als Alternative eine Möglichkeit, den "Forward" Verlauf zu entfernen, ohne einen neuen Zustand zu drücken?

Antwort

34

Sie sind vielleicht schon weiter, aber ... so weit ich weiß, gibt es keine Möglichkeit, einen Verlaufseintrag (oder Status) zu löschen.

Eine Option, die ich untersucht habe, ist die Geschichte selbst in JavaScript zu behandeln und das window.history Objekt als Träger von Arten zu verwenden.

Grundsätzlich, wenn die Seite zuerst geladen wird, erstellen Sie Ihr benutzerdefiniertes Verlaufsobjekt (wir gehen hier mit einem Array, aber verwenden Sie, was für Ihre Situation sinnvoll ist), dann tun Sie Ihre erste pushState. Ich würde Ihr benutzerdefiniertes Verlaufsobjekt als Statusobjekt übergeben, da es sich als nützlich erweisen kann, wenn Sie auch mit Benutzern arbeiten müssen, die von Ihrer App weg navigieren und später wiederkommen.Jetzt

var myHistory = []; 

function pageLoad() { 
    window.history.pushState(myHistory, "<name>", "<url>"); 

    //Load page data. 
} 

, wenn Sie navigieren Sie zu Ihrem eigenen Geschichte Objekt hinzufügen (oder nicht - die Geschichte ist jetzt in Ihren Händen!) Und verwenden replaceState den Browser aus der Schleife zu halten.

function nav_to_details() { 
    myHistory.push("page_im_on_now"); 
    window.history.replaceState(myHistory, "<name>", "<url>"); 

    //Load page data. 
} 

Wenn der Benutzer rückwärts navigiert, werden sie Ihre „Basis“ Zustand (Ihr Zustand Objekt null sein wird) schlagen werden und Sie können die Navigation nach Ihrer benutzerdefinierten Geschichte Objekt behandeln. Danach machst du einen weiteren PushState.

function on_popState() { 
    // Note that some browsers fire popState on initial load, 
    // so you should check your state object and handle things accordingly. 
    // (I did not do that in these examples!) 

    if (myHistory.length > 0) { 
     var pg = myHistory.pop(); 
     window.history.pushState(myHistory, "<name>", "<url>"); 

     //Load page data for "pg". 
    } else { 
     //No "history" - let them exit or keep them in the app. 
    } 
} 

Der Benutzer wird nie in der Lage sein, nach vorne zu navigieren ihre Browser-Tasten verwenden, weil sie immer auf dem neuesten Seite sind.

Aus der Sicht des Browsers, jedes Mal, wenn sie "zurück" gehen, haben sie sofort wieder vorwärts geschoben.

Aus der Sicht des Benutzers sind sie in der Lage, rückwärts durch die Seiten zu navigieren, aber nicht vorwärts (im Grunde simulieren sie das Smartphone- "Seitenstapel" -Modell).

Aus der Sicht des Entwicklers haben Sie jetzt eine hohe Kontrolle darüber, wie der Benutzer durch Ihre Anwendung navigiert, während er dennoch die vertrauten Navigationsschaltflächen in seinem Browser verwenden kann. Sie können Elemente beliebig an beliebiger Stelle in der Verlaufskette hinzufügen/entfernen. Wenn Sie Objekte in Ihrem History-Array verwenden, können Sie zusätzliche Informationen über die Seiten (wie Feldinhalte und Ähnliches) verfolgen.

Sie könnten die Idee auch auf die Vorwärtsnavigation ausweiten. Sie würden 3 Seiten benötigen - eine "Zurück" -Handlerseite, eine "Vorwärts" -Handlerseite und eine "Rest" -Seite dazwischen, wo der Benutzer typischerweise sein wird. Sie müssten dann entlang Ihres Verlaufsobjekts vor- und zurückgehen, anstatt einfach die Objekte zu verschieben.

+0

Hey, danke. Das ist etwas eleganter als das, was ich als Workaround benutzt habe. – slicedtoad

+0

Was ist zu tun, wenn ein Benutzer an dieses Verhalten gewöhnt ist, dann einige Male einen Status erstellt, dann zu einer externen Site navigiert und dann zurück navigiert, und ich nehme an, dass der Verlauf der Navigation der App nun verschwunden ist und die Zurück-Schaltfläche angezeigt wird Sei zuletzt auf dem Haufen. –

+0

Der von history.pushState gedrückte Status wird verfügbar sein, wenn sie zurückkommen (auch wenn sie ihren Browser schließen oder aktualisieren). Einige Browser werden ein Popstate-Ereignis beim Laden der Seite auslösen, andere jedoch nicht (Firefox zum Beispiel). Aber Sie können history.state immer direkt lesen. Wenn Sie das Objekt history.state nicht verwenden, müssen Sie eine andere Methode verwenden, um Ihren Status beizubehalten (wie localStorage). history.state wird automatisch als Teil des Browserverlaufs beibehalten. –