- From: Jonas Sicking <jonas@sicking.cc>
- Date: Wed, 19 Aug 2009 17:35:46 -0700
On Tue, Aug 18, 2009 at 5:04 PM, Justin Lebar<justin.lebar at gmail.com> wrote: > I'm in the process of implementing the HTML5 History API > (History.pushState(), History.clearState(), and the PopState event) in > Firefox. ?I'd like to discuss whether the API might benefit from some > changes. ?To my knowledge, no other browser implements this API, so > I'm assuming we have freedom to make large alterations to it. > > My basic proposal is that History.pushState() be split into a function > for creating new history entries and functions or a property for > getting/setting an object associated with that entry. > > In its current form, the History API allows us to identify session > history entries by way of an arbitrary object, which we pass as the > first argument to pushState() and which we receive as part of the > PopState event when that history entry is activated. ?If the page gets > a null popstate, it's supposed to use the URL to decide what state to > display. > > Notably unsupported by this API is support for pages altering their > saved state. ?For instance, a page might want to save a text box's > edit history to implement a fancy undo. ?It could store the edit > history in a cookie or in the session storage, but then if we loaded > the page twice in the same tab, those two instances would step on each > other when we went back and forth between them. > > The page could just store its state in variables in the document, but > then it would loose that state when the browser crashed or was closed, > or when the browser decided to kick the document out of the history. > > I think this page would be better served by a History.setStateObject() > function, which does exactly what the page wants in a simple fashion. > > We'd still keep the history-entry-creating functionality of > History.pushState() in a new History function (I'll call it > createNewEntry(), but it probably needs a better name), which takes a > title and URL, as pushState() does now. > > The API might be more intuitive if we had a History.stateObject > propery, but I'm concerned that then we'd be promising the page that > we'll keep around literally any objects it wants, including DOM > objects. ?In fact, I'd be happy restricting the state object to being > a string. ?If a page wants to store an object, it can convert it to > JSON, or it can store a GUID as its state string and index into the > session storage. > > Pages could retrieve the state object just as they do now, in a > PopState event, although we'd probably want to change the name of the > event. ?We'd probably want to fire PopState on all loads and history > navigations, since any document might have a state to pop, and even > those documents which didn't call setStateObject() might store state > in their URI which they need to restore when their history entry is > activated. > > Last, I'm not sure that we need the History.clearState() function. > It's confusing (why do we end up at the last entry for the current > document instead of staying at the current entry?) and I haven't been > able to come up with a compelling use case. > > I think the main benefit of these changes is added simplicity. > There's a right and wrong way to use pushState, and > setState/createNewEntry doesn't require such rules. ?But additionally, > these changes allow pages flexibility to do things we haven't yet > thought of. ?I don't know what those things might be, but I suspect > they may be pretty cool. ?:) I agree with Justin (unsurprisingly since we've been doing a fair amount of discussing on the subject). In general when I've been thinking about how to use this API i've had a hard time wrapping my head around the intended way to use it. It wasn't until I started thinking of it in the following way that it made sense: There's two aspects to the API: 1. The ability navigate the user to a new URI without forcing the UA to load a new page. So for example instead of using fragment-identifier hacks, actually change the uri. So for example gmail uses URIs like: https://mail.google.com/mail/?#inbox https://mail.google.com/mail/?#label/personal https://mail.google.com/mail/?#label/whatwg https://mail.google.com/mail/?#label/whatwg/13b4711edac9c1e2 it would be better if you could actually navigate between https://mail.google.com/mail/inbox https://mail.google.com/mail/label/personal https://mail.google.com/mail/label/whatwg https://mail.google.com/mail/label/whatwg/13b4711edac9c1e2 and then use the fragment identifier for what it was intended. 2. The ability to create several session history entries for the same page which the user can navigate between, and use some type of state object to disambiguate between these states. For example in our bug database we allow users to look at attachments, as well as comment on attachments. When starting to comment on an attachment the page changes from displaying the attachment, to displaying a <textarea> pre-populated with the contents of the attachment such that you can add comments to it. It would be nice if switching modes acted like navigation so that you could go back It would further be nice if your comments weren't lost even if you navigate away from the page. Thus if the page could store the comment in the session history entry it could always be retrieved when the user goes page to that state. Ideally this would happen even if the UA crashes, or if user navigates far enough away from the page that the page's Document is unloaded from memory. When thinking about it this way it became pretty clear that pushState was not the right API for two reasons. First of all it combines the two aspects into a single function call. The same function is used to navigate the user to a different API, as is used to associate data with a history entry. Instead having createNewEntry which deals with the first use case, and setState which (partially) deals with the second makes more sense. Though there is actually two features in the second use case: 2a. Create new session history entries for the current page. 2b. Associate data with the current session history entry. setState only does 2b. However createNewEntry could cover 2a if we make both the uri and title arguments optional. Further, it makes sense if the browser tries to save the stored state across restarts or crashes. And across the Document being unloaded from memory. Lastly, I don't see where clearState fits into this. It seems to me that it can be removed. / Jonas
Received on Wednesday, 19 August 2009 17:35:46 UTC