The sequence of Document
s in a browsing
context is its session history.
History
objects provide a representation of the
pages in the session history of browsing contexts. Each browsing
context, including nested browsing contexts, has a distinct session
history.
Each Document
object in a browsing
context's session history is associated with a
unique instance of the History
object, although they
all must model the same underlying session history.
History
objects represent their browsing
context's session history as a flat list of session history entries. Each
session history entry consists of either a
URL or a state object, or both.
Titles associated with session history entries need not have any relation
with the current title
of the
Document
. The title of a session history
entry is intended to explain the state of the document at
that point, so that the user can navigate the document's
history.
URLs without associated state objects are added to the session history as the user (or script) navigates from page to page.
A state object is an object representing a user interface state.
Pages can add state objects between their entry in the session history and the next ("forward") entry. These are then returned to the script when the user (or script) goes back in the history, thus enabling authors to use the "navigation" metaphor even in one-page applications.
State objects are intended to
be used for two main purposes: first, storing a preparsed
description of the state in the URL so that in the
simple case an author doesn't have to do the parsing (though one
would still need the parsing for handling URLs passed around by users, so it's only a minor
optimization), and second, so that the author can store state that
one wouldn't store in the URL because it only applies to the current
Document
instance and it would have to be reconstructed
if a new Document
were opened.
An example of the latter would be something like keeping track of
the precise coordinate from which a popup div
was made
to animate, so that if the user goes back, it can be made to animate
to the same location. Or alternatively, it could be used to keep a
pointer into a cache of data that would be fetched from the server
based on the information in the URL, so that when going
back and forward, the information doesn't have to be fetched
again.
At any point, one of the entries in the session history is the
current entry. This is the entry representing the
active document of the browsing
context. The current entry is usually an entry
for the location of the
Document
. However, it can also be one of the entries
for state objects added to the
history by that document.
An entry with persisted user state is one that also has user-agent defined state. This specification does not specify what kind of state can be stored.
For example, some user agents might want to persist the scroll position, or the values of form controls.
Entries that consist of state
objects share the same Document
as the entry for
the page that was active when they were added.
Contiguous entries that differ just by fragment identifier also
share the same Document
.
All entries that share the same
Document
(and that are therefore merely different
states of one particular document) are contiguous by definition.
History
interfaceinterface History { readonly attribute long length; readonly attribute any state; void go(in optional long delta); void back(); void forward(); void pushState(in any data, in DOMString title, in optional DOMString url); void replaceState(in any data, in DOMString title, in optional DOMString url); };
history
. length
Returns the number of entries in the joint session history.
history
. state
Returns the current state object.
history
. go
( [ delta ] )Goes back or forward the specified number of steps in the joint session history.
A zero delta will reload the current page.
If the delta is out of range, does nothing.
history
. back
()Goes back one step in the joint session history.
If there is no previous page, does nothing.
history
. forward
()Goes forward one step in the joint session history.
If there is no next page, does nothing.
history
. pushState
(data, title [, url ] )Pushes the given data onto the session history, with the given title, and, if provided, the given URL.
history
. replaceState
(data, title [, url ] )Updates the current entry in the session history to have the given data, title, and, if provided, URL.
The joint session history of a History
object is the union of all the session
histories of all browsing
contexts of all the fully active
Document
objects that share the History
object's top-level browsing context, with all the
entries that are current entries
in their respective session
histories removed except for the current entry of the
joint session history.
The current entry of the joint session history is the entry that most recently became a current entry in its session history.
Entries in the joint session history are ordered chronologically by the time they were added to their respective session histories. (Since all these browsing contexts by definition share an event loop, there is always a well-defined sequential order in which their session histories had their entries added.) Each entry has an index; the earliest entry has index 0, and the subsequent entries are numbered with consecutively increasing integers (1, 2, 3, etc).
Consider a game where the user can navigate along a line, such that the user is always at some coordinate, and such that the user can bookmark the page corresponding to a particular coordinate, to return to it later.
A static page implementing the x=5 position in such a game could look like the following:
<!DOCTYPE HTML> <!-- this is http://example.com/line?x=5 --> <title>Line Game - 5</title> <p>You are at coordinate 5 on the line.</p> <p> <a href="?x=6">Advance to 6</a> or <a href="?x=4">retreat to 4</a>? </p>
The problem with such a system is that each time the user clicks, the whole page has to be reloaded. Here instead is another way of doing it, using script:
<!DOCTYPE HTML> <!-- this starts off as http://example.com/line?x=5 --> <title>Line Game - 5</title> <p>You are at coordinate <span id="coord">5</span> on the line.</p> <p> <a href="?x=6" onclick="go(1); return false;">Advance to 6</a> or <a href="?x=4" onclick="go(-1); return false;">retreat to 4</a>? </p> <script> var currentPage = 5; // prefilled by server function go(d) { setupPage(currentPage + d); history.pushState(currentPage, document.title, '?x=' + currentPage); } onpopstate = function(event) { setupPage(event.state); } function setupPage(page) { currentPage = page; document.title = 'Line Game - ' + currentPage; document.getElementById('coord').textContent = currentPage; document.links[0].href = '?x=' + (currentPage+1); document.links[0].textContent = 'Advance to ' + (currentPage+1); document.links[1].href = '?x=' + (currentPage-1); document.links[1].textContent = 'retreat to ' + (currentPage-1); } </script>
In systems without script, this still works like the previous example. However, users that do have script support can now navigate much faster, since there is no network access for the same experience. Furthermore, contrary to the experience the user would have with just a naïve script-based approach, bookmarking and navigating the session history still work.
In the example above, the data argument to
the pushState()
method
is the same information as would be sent to the server, but in a
more convenient form, so that the script doesn't have to parse the
URL each time the user navigates.
Applications might not use the same title for a session
history entry as the value of the document's
title
element at that time. For example, here is a
simple page that shows a block in the title
element.
Clearly, when navigating backwards to a previous state the user
does not go back in time, and therefore it would be inappropriate
to put the time in the session history title.
<!DOCTYPE HTML> <TITLE>Line</TITLE> <SCRIPT> setInterval(function () { document.title = 'Line - ' + new Date(); }, 1000); var i = 1; function inc() { set(i+1); history.pushState(i, 'Line - ' + i); } function set(newI) { i = newI; document.forms.F.I.value = newI; } </SCRIPT> <BODY ONPOPSTATE="set(event.state)"> <FORM NAME=F> State: <OUTPUT NAME=I>1</OUTPUT> <INPUT VALUE="Increment" TYPE=BUTTON ONCLICK="inc()"> </FORM>
Location
interfaceEach Document
object in a browsing
context's session history is associated with a unique
instance of a Location
object.
location
[ = value ]location
[ = value ]Returns a Location
object with the current page's location.
Can be set, to navigate to another page.
Location
objects provide a representation of their document's current
address, and allow the current entry of the
browsing context's session history to be changed, by
adding or replacing entries in the history
object.
interface Location { stringifier attribute DOMString href; void assign(in DOMString url); void replace(in DOMString url); void reload(); // URL decomposition IDL attributes attribute DOMString protocol; attribute DOMString host; attribute DOMString hostname; attribute DOMString port; attribute DOMString pathname; attribute DOMString search; attribute DOMString hash; // resolving relative URLs DOMString resolveURL(in DOMString url); };
href
[ = value ]Returns the current page's location.
Can be set, to navigate to another page.
assign
(url)Navigates to the given page.
replace
(url)Removes the current page from the session history and navigates to the given page.
reload
()Reloads the current page.
resolveURL
(url)Resolves the given relative URL to an absolute URL.
The Location
interface also has the complement of
URL decomposition IDL attributes, protocol
, host
, port
, hostname
, pathname
, search
, and hash
.
The popstate
event
is fired in certain cases when navigating to a session history
entry.
interface PopStateEvent : Event { readonly attribute any state; void initPopStateEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in any stateArg); };
state
Returns a copy of the information that was provided to pushState()
or replaceState()
.
The hashchange
event is fired when navigating to a session history
entry whose URL differs from that of the
previous one only in the fragment identifier.
interface HashChangeEvent : Event { readonly attribute DOMString oldURL; readonly attribute DOMString newURL; void initHashChangeEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString oldURLArg, in DOMString newURLArg); };
oldURL
Returns the URL of the session history entry that was previously current.
newURL
Returns the URL of the session history entry that is now current.
The pageshow
event
is fired when traversing to a session history
entry.
The pagehide
event is fired when traversing from a session history
entry.
interface PageTransitionEvent : Event { readonly attribute boolean persisted; void initPageTransitionEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in boolean persistedArg); };
persisted
Returns false if the page is newly being loaded (and the load
event will fire). Otherwise, returns true.
interface BeforeUnloadEvent : Event { attribute DOMString returnValue; };
returnValue
[ = value ]Returns the current return value of the event (the message to show the user).
Can be set, to update the message.
There are no BeforeUnloadEvent
-specific
initialization methods.