Re: [whatwg] pushState and session history issues
On Thu, 12 Aug 2010, Mihai Parparita wrote: On Thu, Aug 12, 2010 at 4:56 PM, Ian Hickson i...@hixie.ch wrote: On Tue, 27 Jul 2010, Mihai Parparita wrote: https://webkit.org/b/42861 has more tests, but briefly, the behavior in the latest stable versions of these browser is: - Firefox will not create a session history entry if the navigation is executed inline, or during an onload handler - Chrome will not create a session history entry if the navigation is executed inline, or within 5 seconds of the onload handler firing - Safari will always create a session history entry - IE will not create a session history entry for hash changes during onload only My proposed change to WebKit is to not create a session history entry for location changes that happen before onload fires if they are not in response to a user gesture. I would also be modifying Chrome to remove its custom logic for this and just inherit WebKit's. Does anyone see any compatibility problems with this? Should the HTML5 history section mention anything about navigations caused script vs. user gestures*? I realize that replace() should obviate the need for such a heuristic, but given that 1) other browsers seem to do this and 2) sites like hp.com don't get it right, there may be a need for it. * It only alludes to something similar: In addition, a user agent could ignore calls to pushState() that are invoked on a timer, or from event listeners that are not triggered in response to a clear user action, or that are invoked in rapid succession. IE's behaviour seems the narrowest; would it be acceptable? Failing that, how about any navigations until the end of the load event task? Based on the way the discussion has evolved in https://webkit.org/b/42861, the consensus is that your second option (any navigations until the end of the load event task) is preferable (given that sites already do this, e.g. the Wikipedia mobile redirect). Would form submits also be counted as navigation? Navigation is anything that runs the navigate algorithm in the spec, which is everything from scripted form submission to a user typing a URL in the location bar. The proposal here would be to just assume a scripted navigation is done with replacement enabled in the condition described above, right? And yes, this woud be just be navigation with replacement enabled. Here is a list of the ways the spec currently lets you trigger navigation, and what I've done for each one regarding this issue: meta http-equiv=refresh - unchanged; this already does replacement anyway. iframe src and srcdoc, frame - unchanged; these aren't redirects. object data - unchanged; always does replacement anyway. form submission - changed to do replacement if the submission was invoked from .submit() and the load, pageshow, and popstate events have not yet finished being fired for this document. hyperlinks - unchanged; these are assumed to be new documents, not redirects, and so should not replace. window.open - unchanged; if opening a new window or if the 'replace' argument is set, then this already did replacement; in the case of navigating another window, Firefox didn't do anything special, IE doesn't seem to either though that seems to actually differ based on how you measure it (e.g. history.length vs the UI's back button). location.href - changed like form submission. location.assign() - unchanged, on the assumption that we always want this to not replace, since if you want to replace you can use...: location.replace() - unchanged, since it always replaces. location.reload() - unchanged; always replaces. user reload UI - unchanged; always replaces. user manually opening of a link from inside a sandbox - unchanged, mostly a UI issue. history.back()/.forward() and user history traversal - unchanged; this is an internal issue (entry update) and is supposed to be transparent to the user and script as far as possible. showModalDialog - unchanged; always replaces. opening a link from the OS (e.g. following an HTTP link from an IM app or trying to open a resource that matched a registerProtocolHandler() registration) - unchanged, same as hyperlinks. handling an encoding change during parsing - unchanged; always replaces. following cite= links - unchanged, same as hyperlinks. On Fri, 27 Aug 2010, Mihai Parparita wrote: On Fri, Aug 27, 2010 at 4:03 PM, Ian Hickson i...@hixie.ch wrote: BTW, there's another problem with this API, which is that since popstates are dropped while the document is loading, calling pushState() while the document is loading leads to a very confused state. Should we make pushState() throw an exception if called before load? (replaceState() is probably ok, though even that's a bit dodgy.) This seems
[whatwg] pushState and session history issues
On Mon, 7 Jun 2010, Mike Wilson wrote: Ian Hickson wrote: Mike Wilson wrote: the semantic contract is coming closer and closer to that of the other storage APIs, so I think it would be an advantage to use the same interface as well. I don't see the relevance of storage APIs here. This isn't a storage model. It's more a callback model. I disagree. Once an API persists state between page loads it deserves to be regarded as a storage API and not just a callback API. The data objects supplied in pushState calls may be persisted for the lifetime of their browsing context (unless history entry is removed), just like data in session storage. I'm not really convinced that this makes it a storage API, nor am I convinced that we should make all the storage mechanisms have the same API, even if it did. There should be good reasons why not to reuse existing API patterns. Why is pushState inventing a new API pattern where a copy of the state is forwarded through new methods and events, instead of accessing it through a storage facade (see sessionStorage and localStorage) as in WebStorage? Well, it was defined first, to start with. :-) Why is pushState defining a more restrictive model to state access (read once / write anytime) compared to WebStorage (read anytime / write anytime) ? What use-cases are solvable in the current pushState model but not in a WebStorage-style model? (see below for WebStorage-style example) There are often many ways to solve these kinds of problems. When pushState() was designed, it was envisioned as a mechanism to annotate the session history, which is why it ended up being the way it is. Ian Hickson wrote: Mike Wilson wrote: Why not use the same API as in Web Storage: interface Storage { readonly attribute unsigned long length; getter DOMString key(in unsigned long index); getter any getItem(in DOMString key); setter creator void setItem(in DOMString key, in any data); deleter void removeItem(in DOMString key); void clear(); }; and make the current entry's Storage instance always available as f ex: interface History { readonly attribute Storage state; } Then pushState's state parameter may be removed and there is no longer a need for the replaceState method. I don't understand how this would work. When does the history get updated in this model? The pushState method (without state parameter and possibly renamed) remains to create a new session history entry: function() { history.state.setItem(a, 1); // set on current history entry history.pushState(title, url); // create new history entry history.state.getItem(a); // get from new history entry (null) history.state.setItem(a, 2); // set on new history entry } How do you know you've gone back in history? The popstate event (without state attribute) remains to inform us that history entry has been switched and that the corresponding data is now available through history.state. Yeah, we could have done it that way. I don't know that it's better or worse, personally. On Wed, 23 Jun 2010, Justin Lebar wrote: Safari 5 and Chrome 5 recently shipped the history.pushState and replaceState methods. Firefox 4 will also include those methods when it ships. pushState and replaceState take three arguments: An opaque data object, a title, and an optional URL. Currently, Safari and Chrome both ignore the title parameter. Jonas Sicking jo...@sicking.cc and I have been talking with Brady Eidson beid...@apple.com and Darin Fisher da...@chromium.org, about what we can do to clean up this API, since having an unused parameter in our brand-new functions is unfortunate. Ideally, we might change the pushState and replaceState methods themselves, perhaps changing them so they only take a URL and an optional data object. But since Chrome and Safari have already shipped the method, and since we hear that the functions are already being used on the web, it's probably too late to add or remove arguments from the functions. It seems that the intent of the spec as it stands is that the title parameter should show up in the session history list (shown e.g. when you click the down arrow next to the forward button), but not in the application's title bar. We think this is confusing (as evidence, observe that two browsers skipped this step!) and adds a lot of complexity for a small amount of gain, so we're not in favor of this approach. If modifying the document's title in the session history list is a desirable feature, then we could expose that property to the DOM just as we expose document.title. Seeing as we're stuck with the title argument in pushState and replaceState, we propose that it modify document.title in an intuitive way: * Before we unload a history entry, we save document.title into
Re: [whatwg] pushState and session history issues
On Thu, Aug 12, 2010 at 4:56 PM, Ian Hickson i...@hixie.ch wrote: On Tue, 27 Jul 2010, Mihai Parparita wrote: https://webkit.org/b/42861 has more tests, but briefly, the behavior in the latest stable versions of these browser is: - Firefox will not create a session history entry if the navigation is executed inline, or during an onload handler - Chrome will not create a session history entry if the navigation is executed inline, or within 5 seconds of the onload handler firing - Safari will always create a session history entry - IE will not create a session history entry for hash changes during onload only My proposed change to WebKit is to not create a session history entry for location changes that happen before onload fires if they are not in response to a user gesture. I would also be modifying Chrome to remove its custom logic for this and just inherit WebKit's. Does anyone see any compatibility problems with this? Should the HTML5 history section mention anything about navigations caused script vs. user gestures*? I realize that replace() should obviate the need for such a heuristic, but given that 1) other browsers seem to do this and 2) sites like hp.com don't get it right, there may be a need for it. * It only alludes to something similar: In addition, a user agent could ignore calls to pushState() that are invoked on a timer, or from event listeners that are not triggered in response to a clear user action, or that are invoked in rapid succession. IE's behaviour seems the narrowest; would it be acceptable? Failing that, how about any navigations until the end of the load event task? The proposal here would be to just assume a scripted navigation is done with replacement enabled in the condition described above, right? Based on the way the discussion has evolved in https://webkit.org/b/42861, the consensus is that your second option (any navigations until the end of the load event task) is preferable (given that sites already do this, e.g. the Wikipedia mobile redirect). Would form submits also be counted as navigation? And yes, this woud be just be navigation with replacement enabled. Mihai
[whatwg] pushState / replaceState nits
In section 6.10.2: The pushState(data, title, url) method adds a state object to the history. perhaps should be ... adds a state object *entry* to the history. The replaceState(data, title, url) method updates the current entry in the history to have a state object. perhaps should be The replaceState(data, title, url) method adds a stateObject to the current history entry or modifies (updates?) the entry's stateObject. When either of these methods are invoked should be When either of these methods is invoked. -Justin
Re: [whatwg] pushState
On Fri, 25 Jul 2008, Jonas Sicking wrote: So to back up. There are a few things that are important to me: 1. The session history (SH) entries created in this way should act as much like normal SH entries as possible to the user. I.e. the user doesn't care if clicking what looks like a link results in a navigation or a .pushState call. 2. That this API allows pages to be written that survives a browser restart. This is to prevent data loss in case of crash, and to increase chances that users install security updates which require restart as soon as possible. 3. That the API encourages bug-free pages. I.e. pages that use the API 'correctly'. Just 1 in itself means that we can't just kill SH entries just because the Document they were created from goes away from fastback. If I browse away from a gmail and see 5 pages in my SH list then I would be very disappointed if those 5 pages just disappeared because I happened to be browsing around in another window which ate up the fastback cache. Similarly, a mobile device might not have a fastback cache at all. It would look very strange if while i'm staying on the gmail site i'm able to go 'back' to what to me looks like various different pages. But as soon as i go to some other site, I loose all those pages and can only go back directly to the first gmail page. So we must definitely store the pushed SH data in such a way that if the Document is recreated the data survives. This applies whether the URL of my browser changes or not while I'm doing this browsing. The rendering changing is more important than the URL changing for a user. So what I think we should do is to enforce that 'data' is a JSON serializable object. When a Document is destroyed (due to eviction from the fastback cache or due to not being cachable) we don't touch the SH entries associated with that document. Ok. I've used the new structured clone concept to sanitise the data and make a copy instead of storing the actual object. This enables us to keep them around even when the Document is evicted. One thing I had to change is that now if you go from state 1 to state 3, state 2 is no longer popped. You can move discontinuously through the states. When entering a SH state for which a Document has been destroyed, we load the URL associated with that SH entry. After the 'load' event for the Document has fired, and if a data object was provided in the pushState call for the SH entry, we fire a PopStateEvent event containing the data stored for the object. The same thing happens if the user clicks the reload button while on an SH entry created using pushState. The URL for that entry is loaded and after the 'load' event has fired, if a data object was provided during the pushState call, a PopStateEvent is fired with that data. The timing here is difficult. What should happen if while the page is loading, the user navigates to a link with a fragment identifier, or invokes pushState, or navigates to another SH entry with a state object? I'll see what I can come up with. It may be that I'll just delay all popstate and hashchanged events until the 'load' event has fired, and then I'll fire both for the current state. To minimize the difference between when a SH entry is recovered from the fastback cache, compared to when the document is reparsed, the Location object should be changed to reflect the new URL whenever pushState is called with a url. The advantage of changing the Location object is that this makes the page behave the same no matter of if it has been reloaded or not. Setting the Location objects value will cause reloading vs. scrolling vs. do nothing in the same cases. Similarly reading the Location will return the same thing no matter of if there has been a reload or not. I just found that I wasn't even updating the Location for fragment identifier changes. Oops. I'll fix that and give the behavior you describe when I fix bug 6437. http://www.w3.org/Bugs/Public/show_bug.cgi?id=6437 -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] pushState
On Sun, 03 Aug 2008 22:47:24 +0200, Jonas Sicking [EMAIL PROTECTED] wrote: Personally I think keeping the URL is fine. We can never entirely prevent pages from having bugs. But instead encourage the safe transitions, and always use safe-looking transitions in examples in the spec. FWIW, I think the URL argument is the best part of this feature. I don't want to lose it! -- Anne van Kesteren http://annevankesteren.nl/ http://www.opera.com/
Re: [whatwg] pushState
On Sun, 3 Aug 2008, Jonas Sicking wrote: The problem I have with this is that it increases the number of possible user-visible behaviours and failure scenarios: - same Document, script knows how to handle data. - different Document, script knows how to handle data. - same URL, different Document, data ignored. - different URL, different Document, script knows how to handle data, but copying URL fails to work as expected. - different URL, different Document, data ignored. I'm actually more worried about the URL thing causing bugs than the data thing. * To avoid bad user experience behavior the site has to send almost exactly the same markup for both URLs, i.e. both for the page that called pushState, and for the page served for the URL in the URL argument in the pushState call. Equivalently though, to avoid a bad experience, a site will have to provide a statically generated URL version anyway, even if data is provided, to handle the bookmark case. * Entering a URL that is results in a 404 (or any other non-succcess value). This works fine when pushState is called, but fails on reload. Equivalently, if the author screws up the data handling but gets the right URL, then things will work fine in static browsing (with no JS) but as soon as you enable JS in a browser that does pushState(), things will break if you go back. Additionally, if we allow the data parameter to be preserved across Document recreations there is also: * Both URLs have to react the same way when a popstate event is fired. I am proposing getting rid of popstate and the data altogether. So I think we should either drop the URL argument entirely and say that URL transitions are too risky. This would fail to address one of the core use cases, namely bookmarkability, so this isn't really an option. Or we should leave the spec as is (but require that data is serializeable) and just encourage people not to transition between wildly different pages. Well I'm fine with leaving the spec as is, obviously, but if we have the data object, especially if it can only be used with one Document as in the current spec, I think it would be very confusing if exceptions were raised when things like elements were put into the data. It also seems like it wouldn't really gain us anything -- in the cross-session case (restarting the browser, etc) these data objects, according to the spec today, would be thrown out anyway. If we want to handle the cross-Document case (i.e. if we want to never have entries disappear from the session history) then I think we are better off just getting rid of the data argument altogether and always using the URL field. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] pushState
Ian Hickson wrote: On Tue, 29 Jul 2008, Jonas Sicking wrote: I'll check with the ECMA Script folks, but this one might be an alternative to link to: http://wiki.ecmascript.org/doku.php?id=es3.1:json_support State that the object passed as 'data' is passed to JSON.parse with the second argument not specified. Any exception thrown is forwarded out to the caller of pushState as usual. Interesting, thanks. Doesn't really define it clearly though. :-( When entering a SH state for which a Document has been destroyed, we load the URL associated with that SH entry. After the 'load' event for the Document has fired, and if a data object was provided in the pushState call for the SH entry, we fire a PopStateEvent event containing the data stored for the object. How would this work with bookmarking? Just as specified (or at least intended) in the spec right now. Say that the user starts on page1.html bookmark (bookmarks page1.html) pushState(title, data) bookmark (bookmarks page1.html) pushState(title, data, page2.html) bookmark (bookmarks page2.html) Additionally, a UA is free to add the ability to store the data parameter in its bookmark storage. For example firefox under some circumstances flags URIs in the bookmark store as POST URIs, i.e. they should be fetched with POST rather than GET (this is specifically for search engine bookmarks). Similarly the data can be stored alongside the URI for the bookmark, however this is optional, just like the fastback cache. The problem I have with this is that it increases the number of possible user-visible behaviours and failure scenarios: - same Document, script knows how to handle data. - different Document, script knows how to handle data. - same URL, different Document, data ignored. - different URL, different Document, script knows how to handle data, but copying URL fails to work as expected. - different URL, different Document, data ignored. I'm actually more worried about the URL thing causing bugs than the data thing. * To avoid bad user experience behavior the site has to send almost exactly the same markup for both URLs, i.e. both for the page that called pushState, and for the page served for the URL in the URL argument in the pushState call. * Entering a URL that is results in a 404 (or any other non-succcess value). This works fine when pushState is called, but fails on reload. This applies no matter which solution we choose for the data parameter. Additionally, if we allow the data parameter to be preserved across Document recreations there is also: * Both URLs have to react the same way when a popstate event is fired. However all these can be seen as variants of the first bullet. If the page serves the same markup it wouldn't be a 404, and it should deal fine with the popstate event. In other words. If a page uses pushState to transition from https://bugzilla.mozilla.org/show_bug.cgi?id=123456 to https://bugzilla.mozilla.org/show_bug.cgi?id=321321 then things are likely to work fine. However if a page tries to use pushState to transition between https://bugzilla.mozilla.org/show_bug.cgi?id=123456 and https://bugzilla.mozilla.org/query.cgi then the risk of something going wrong is quite big. I think this will be true no matter if the data parameter is supported or not. So I think we should either drop the URL argument entirely and say that URL transitions are too risky. Or we should leave the spec as is (but require that data is serializeable) and just encourage people not to transition between wildly different pages. Personally I think keeping the URL is fine. We can never entirely prevent pages from having bugs. But instead encourage the safe transitions, and always use safe-looking transitions in examples in the spec. / Jonas
Re: [whatwg] pushState
Ian Hickson wrote: On Fri, 25 Jul 2008, Jonas Sicking wrote: So what I think we should do is to enforce that 'data' is a JSON serializable object. (We need a better term -- and definition -- for this.) I'll check with the ECMA Script folks, but this one might be an alternative to link to: http://wiki.ecmascript.org/doku.php?id=es3.1:json_support State that the object passed as 'data' is passed to JSON.parse with the second argument not specified. Any exception thrown is forwarded out to the caller of pushState as usual. When entering a SH state for which a Document has been destroyed, we load the URL associated with that SH entry. After the 'load' event for the Document has fired, and if a data object was provided in the pushState call for the SH entry, we fire a PopStateEvent event containing the data stored for the object. How would this work with bookmarking? Just as specified (or at least intended) in the spec right now. Say that the user starts on page1.html bookmark (bookmarks page1.html) pushState(title, data) bookmark (bookmarks page1.html) pushState(title, data, page2.html) bookmark (bookmarks page2.html) Additionally, a UA is free to add the ability to store the data parameter in its bookmark storage. For example firefox under some circumstances flags URIs in the bookmark store as POST URIs, i.e. they should be fetched with POST rather than GET (this is specifically for search engine bookmarks). Similarly the data can be stored alongside the URI for the bookmark, however this is optional, just like the fastback cache. / Jonas
Re: [whatwg] pushState
On Tue, 29 Jul 2008, Jonas Sicking wrote: I'll check with the ECMA Script folks, but this one might be an alternative to link to: http://wiki.ecmascript.org/doku.php?id=es3.1:json_support State that the object passed as 'data' is passed to JSON.parse with the second argument not specified. Any exception thrown is forwarded out to the caller of pushState as usual. Interesting, thanks. Doesn't really define it clearly though. :-( When entering a SH state for which a Document has been destroyed, we load the URL associated with that SH entry. After the 'load' event for the Document has fired, and if a data object was provided in the pushState call for the SH entry, we fire a PopStateEvent event containing the data stored for the object. How would this work with bookmarking? Just as specified (or at least intended) in the spec right now. Say that the user starts on page1.html bookmark (bookmarks page1.html) pushState(title, data) bookmark (bookmarks page1.html) pushState(title, data, page2.html) bookmark (bookmarks page2.html) Additionally, a UA is free to add the ability to store the data parameter in its bookmark storage. For example firefox under some circumstances flags URIs in the bookmark store as POST URIs, i.e. they should be fetched with POST rather than GET (this is specifically for search engine bookmarks). Similarly the data can be stored alongside the URI for the bookmark, however this is optional, just like the fastback cache. The problem I have with this is that it increases the number of possible user-visible behaviours and failure scenarios: - same Document, script knows how to handle data. - different Document, script knows how to handle data. - same URL, different Document, data ignored. - different URL, different Document, script knows how to handle data, but copying URL fails to work as expected. - different URL, different Document, data ignored. If we want to not allow same-Document entries to share state using actual pointers into their state, I'd rather drop the data thing altogether, and only use URLs. That way the author doesn't have to worry about having multiple ways to carry state data around, and there's a clean way of migrating from today's hash-only approach -- keep using the hash. What I'm suggesting gets rid of the: void pushState(in DOMObject data, in DOMString title); ...and makes the only pushState() definition be: void pushState(in DOMObject url, in DOMString title); When the user navigates the session history amongst entries with different URLs that happen to have the same Document because they were added with pushState(), we fire an event. We drop all the stuff about the data argument. We make pushState() change the UI and the Location object. (The event we fire could be an event that we say always fires just after onload as well, so that if a page supports this stuff, it'll always support it even when you go straight to that URL.) This way, bookmarking and copying URLs all works fine. What do you think? What do other people think? Is losing the ability to link to JS objects within the Document itself a problem? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] pushState
On Fri, 25 Jul 2008, Jonas Sicking wrote: So what I think we should do is to enforce that 'data' is a JSON serializable object. (We need a better term -- and definition -- for this.) When entering a SH state for which a Document has been destroyed, we load the URL associated with that SH entry. After the 'load' event for the Document has fired, and if a data object was provided in the pushState call for the SH entry, we fire a PopStateEvent event containing the data stored for the object. How would this work with bookmarking? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] pushState
Jonas Sicking wrote: To minimize the difference between when a SH entry is recovered from the fastback cache, compared to when the document is reparsed, the Location object should be changed to reflect the new URL whenever pushState is called with a url. The advantage of changing the Location object is that this makes the page behave the same no matter of if it has been reloaded or not. Setting the Location objects value will cause reloading vs. scrolling vs. do nothing in the same cases. Similarly reading the Location will return the same thing no matter of if there has been a reload or not. Yes, this is different from how legacy browsers behave. However the whole point of this API is to improve on the current iframe hacks. If we didn't there would be no point in adding a new API as it wouldn't be worth the code fork for users. Reloads mostly don't work with the iframe hack anyway so you'll end up with vastly different behavior no matter what. And if we're not considering the reload case then the hashchanged event should be enough. This isn't a big deal though as far as I can think of. Only if your application runs inside someone elses iframe and that outer app is intimately interacting with you I can see that it makes a difference. This doesn't seem common enough that we should prioritize for it. Additionally, I just noticed that gmail does set the location.hash of the top window. So gmail would want to change the Location object for compat with legacy browsers. And a library that used a hidden iframe for legacy browsers and really wanted to be compatible as far as the Location object goes (though i'm still unconvinced that anyone cares) could use iframe.history.pushState(); / Jonas
Re: [whatwg] pushState
It is not customary for desktop applications to change the window title in response to current state of the document it displays. A Web browser is a desktop application and it should not exhibit such behavior either. The place to store information about the latest user action is the Edit menu, although it is optional. The page content can change after page reload thereby making some elements of session state useless or not applicable. This would still be the same page but different content. You can still make arbitrary data into JSON data using e.g. XPath or another moniker convention but, while technically possible, it would hardly be a success in lack of application-dependent intricate logic (consider e.g. the Alias Manager and its lame substitute in Microsoft Windows). Chris -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Jonas Sicking Sent: Friday, July 25, 2008 11:45 PM To: Ian Hickson Cc: whatwg Subject: Re: [whatwg] pushState Ian Hickson wrote: On Fri, 25 Jul 2008, Jonas Sicking wrote: What is the purpose of the 'title' argument? Is the idea that the UA will show that where it usually shows the title of the page? If so the title isn't purely advisory as it should probably affect document.title as well. This would seem like a good idea to me. The idea is to use this title in the session history. It's distinct than the title and document.title because when the session history might need to say something like Mail - after opening 'compose mail', Mail - after typing paragraph ending in 'JSON-ifyable object.', and so forth, while the whole time the actual page title just says Mail - New Mail. So the idea is that this is the title that we'd display for example in the drop down where you can select a history entry to navigate to? If so, why wouldn't you want document.title to also say Mail - after opening 'compose mail' as well? Seems like good UI to keep the two in sync. What is the purpose of the url attribute? Why would you want to reload a separate page when returning to a given state, then what was used to load that state initially? If the Document gets discarded (e.g. it gets evicted from the bfcache), the URL allows the client to still pretend it has the state, allowing the server to regenerate it based on the data in the URL. But why would you want to recreate the same document using a different page than the page that originally created the document. I.e. if I have a single page that I use to show various views, why would I all of a sudden want to use another page to render one of those views just because the user restarted the browser?
Re: [whatwg] pushState
On Fri, 25 Jul 2008, Jonas Sicking wrote: What is the purpose of the 'title' argument? Is the idea that the UA will show that where it usually shows the title of the page? If so the title isn't purely advisory as it should probably affect document.title as well. This would seem like a good idea to me. The idea is to use this title in the session history. It's distinct than the title and document.title because when the session history might need to say something like Mail - after opening 'compose mail', Mail - after typing paragraph ending in 'JSON-ifyable object.', and so forth, while the whole time the actual page title just says Mail - New Mail. What is the purpose of the url attribute? Why would you want to reload a separate page when returning to a given state, then what was used to load that state initially? If the Document gets discarded (e.g. it gets evicted from the bfcache), the URL allows the client to still pretend it has the state, allowing the server to regenerate it based on the data in the URL. Also, the URL can be used when bookmarking the page. It could also be displayed in the location bar. (The Location object should not be updated, however.) I would like to store the session states created using pushState on disk so that the state can be restored in the event of a crash or a restart. The only thing that would be needed to support this is that the 'data' object is a string rather than a generic object. This is because a generic object can't be serialized and saved to disk. Actually, what would be even better is if the API accepted a string or a JSON-ifyable object. That's what the URL is for. The data will, in many non-trivial cases, be some very complex object with actual Object references and pointers to DOM nodes and so forth. Imagine, for instance, a text editor using this. I don't think we want to require that the data be plain structured data (is there a term for this better than JSON-ifiable?), as that would preclude a number of complex cases. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] pushState
On Fri, 25 Jul 2008, Jonas Sicking wrote: What is the purpose of the 'title' argument? Is the idea that the UA will show that where it usually shows the title of the page? If so the title isn't purely advisory as it should probably affect document.title as well. This would seem like a good idea to me. The idea is to use this title in the session history. It's distinct than the title and document.title because when the session history might need to say something like Mail - after opening 'compose mail', Mail - after typing paragraph ending in 'JSON-ifyable object.', and so forth, while the whole time the actual page title just says Mail - New Mail. What is the purpose of the url attribute? Why would you want to reload a separate page when returning to a given state, then what was used to load that state initially? If the Document gets discarded (e.g. it gets evicted from the bfcache), the URL allows the client to still pretend it has the state, allowing the server to regenerate it based on the data in the URL. Also, the URL can be used when bookmarking the page. It could also be displayed in the location bar. (The Location object should not be updated, however.) I would like to store the session states created using pushState on disk so that the state can be restored in the event of a crash or a restart. The only thing that would be needed to support this is that the 'data' object is a string rather than a generic object. This is because a generic object can't be serialized and saved to disk. Actually, what would be even better is if the API accepted a string or a JSON-ifyable object. That's what the URL is for. The data will, in many non-trivial cases, be some very complex object with actual Object references and pointers to DOM nodes and so forth. Imagine, for instance, a text editor using this. I don't think we want to require that the data be plain structured data (is there a term for this better than JSON-ifiable?), as that would preclude a number of complex cases. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] pushState
Ian Hickson wrote: On Fri, 25 Jul 2008, Jonas Sicking wrote: What is the purpose of the 'title' argument? Is the idea that the UA will show that where it usually shows the title of the page? If so the title isn't purely advisory as it should probably affect document.title as well. This would seem like a good idea to me. The idea is to use this title in the session history. It's distinct than the title and document.title because when the session history might need to say something like Mail - after opening 'compose mail', Mail - after typing paragraph ending in 'JSON-ifyable object.', and so forth, while the whole time the actual page title just says Mail - New Mail. So the idea is that this is the title that we'd display for example in the drop down where you can select a history entry to navigate to? If so, why wouldn't you want document.title to also say Mail - after opening 'compose mail' as well? Seems like good UI to keep the two in sync. What is the purpose of the url attribute? Why would you want to reload a separate page when returning to a given state, then what was used to load that state initially? If the Document gets discarded (e.g. it gets evicted from the bfcache), the URL allows the client to still pretend it has the state, allowing the server to regenerate it based on the data in the URL. But why would you want to recreate the same document using a different page than the page that originally created the document. I.e. if I have a single page that I use to show various views, why would I all of a sudden want to use another page to render one of those views just because the user restarted the browser? Also, the URL can be used when bookmarking the page. It could also be displayed in the location bar. Hmm.. bookmarking is indeed tricky. If a site really want to support bookmarking it seems like the best solution is to use the old hack of setting location.hash. Ideal would be if there was a way to pass parameters to a page as part of a URI. Currently the query parameters are aimed for the server, and the fragment identifier is aimed for where to scroll. I'm not sure if there is syntax that would work for browsers today. (The Location object should not be updated, however.) Why not? I would like to store the session states created using pushState on disk so that the state can be restored in the event of a crash or a restart. The only thing that would be needed to support this is that the 'data' object is a string rather than a generic object. This is because a generic object can't be serialized and saved to disk. Actually, what would be even better is if the API accepted a string or a JSON-ifyable object. That's what the URL is for. Then what is the point of the data object? It seems very bug prone that the data object is just dropped on the floor if the browser is restarted. I.e. we should recommend everyone not to use the data object (except for some sort of cache?) since it will always fail to work if the user restarts the browser. The data will, in many non-trivial cases, be some very complex object with actual Object references and pointers to DOM nodes and so forth. Imagine, for instance, a text editor using this. I don't think we want to require that the data be plain structured data (is there a term for this better than JSON-ifiable?), as that would preclude a number of complex cases. But all those complex cases will fail on a browser restart. It is much better if we encourage people to write stable code. All in all, as the spec is written now it doesn't seem like pushState(...) is providing a lot of value over window.location.hash = Other than that an event is raised on navigation, which we could fix for setting location.hash. My goal with this was to provide a clean API to avoid having to muck around with location.hash trickery (as that really should be used for other things), and that would work in the event of a browser restart. It doesn't seem like the current API meets that goal. / Jonas
Re: [whatwg] pushState
On Fri, 25 Jul 2008, Jonas Sicking wrote: The idea is to use this title in the session history. It's distinct than the title and document.title because when the session history might need to say something like Mail - after opening 'compose mail', Mail - after typing paragraph ending in 'JSON-ifyable object.', and so forth, while the whole time the actual page title just says Mail - New Mail. So the idea is that this is the title that we'd display for example in the drop down where you can select a history entry to navigate to? If so, why wouldn't you want document.title to also say Mail - after opening 'compose mail' as well? Seems like good UI to keep the two in sync. My mail client just keeps the same title the whole time I'm using it. But seeing the name of my mail client six hundred times in a row without any hint as to what each entry means (in the session history) wouldn't be useful. So I guess my answer is no. I think it makes sense that the entry you see in the session history and the entry you see in your OS pager would have different strings. FWIW, the title parameter was added in response to requests in feedback from application authors, who didn't want to change document.title for this. What is the purpose of the url attribute? Why would you want to reload a separate page when returning to a given state, then what was used to load that state initially? If the Document gets discarded (e.g. it gets evicted from the bfcache), the URL allows the client to still pretend it has the state, allowing the server to regenerate it based on the data in the URL. But why would you want to recreate the same document using a different page than the page that originally created the document. I.e. if I have a single page that I use to show various views, why would I all of a sudden want to use another page to render one of those views just because the user restarted the browser? Consider an AJAX version of Bugzilla. Each bug page has a different URL. As you navigate from bug to bug, the URL should change to point to the currently showing bug. But you want to do that without actually doing a reload (changing the Document object). Also, the URL can be used when bookmarking the page. It could also be displayed in the location bar. Hmm.. bookmarking is indeed tricky. If a site really want to support bookmarking it seems like the best solution is to use the old hack of setting location.hash. The hash isn't sent to the server. Again, fwiw, the URL parameter was added in response to author feedback to the effect that only having control over the hash was insufficient for what they wanted to do. (The Location object should not be updated, however.) Why not? Changing it would introduce a gratuitous difference between legacy UAs and UAs implementing this feature, as well as complexity that I'm not sure I really want to have to test. I would like to store the session states created using pushState on disk so that the state can be restored in the event of a crash or a restart. The only thing that would be needed to support this is that the 'data' object is a string rather than a generic object. This is because a generic object can't be serialized and saved to disk. Actually, what would be even better is if the API accepted a string or a JSON-ifyable object. That's what the URL is for. Then what is the point of the data object? It seems very bug prone that the data object is just dropped on the floor if the browser is restarted. I.e. we should recommend everyone not to use the data object (except for some sort of cache?) since it will always fail to work if the user restarts the browser. The data object is for when the page still exists, so that the state can be updated on the fly, e.g. bringing back the exact same video element to the front, or whatever. There are many ways of using this API, just like there are many types of applications. Some applications might be able to represent all state in the URL, others might not be able to represent any state there, others might be in between (e.g. GMail might be able to remember what e-mails you had checked in the data parameter, but would forget that if you bookmarked the page / reloaded the browser). The data will, in many non-trivial cases, be some very complex object with actual Object references and pointers to DOM nodes and so forth. Imagine, for instance, a text editor using this. I don't think we want to require that the data be plain structured data (is there a term for this better than JSON-ifiable?), as that would preclude a number of complex cases. But all those complex cases will fail on a browser restart. It is much better if we encourage people to write stable code. The original feature wasn't expected to work at all across a browser restart. The URL is optional. When it is
Re: [whatwg] pushState
Hmm.. I'm sort of seeing where the spec was trying to head. However I think it too poorly supports the browser restart case. Comments below. Ian Hickson wrote: On Fri, 25 Jul 2008, Jonas Sicking wrote: The idea is to use this title in the session history. It's distinct than the title and document.title because when the session history might need to say something like Mail - after opening 'compose mail', Mail - after typing paragraph ending in 'JSON-ifyable object.', and so forth, while the whole time the actual page title just says Mail - New Mail. So the idea is that this is the title that we'd display for example in the drop down where you can select a history entry to navigate to? If so, why wouldn't you want document.title to also say Mail - after opening 'compose mail' as well? Seems like good UI to keep the two in sync. My mail client just keeps the same title the whole time I'm using it. But seeing the name of my mail client six hundred times in a row without any hint as to what each entry means (in the session history) wouldn't be useful. So I guess my answer is no. I think it makes sense that the entry you see in the session history and the entry you see in your OS pager would have different strings. FWIW, the title parameter was added in response to requests in feedback from application authors, who didn't want to change document.title for this. Requesting is easy. *Why* did they request this? Still seems like better UI design to have this affect the title. The title of my mail client changes to show what part of the UI I'm in. Currently it says whatwg for [EMAIL PROTECTED] indicating that i'm watching the whatwg folder on the [EMAIL PROTECTED] account. What is the purpose of the url attribute? Why would you want to reload a separate page when returning to a given state, then what was used to load that state initially? If the Document gets discarded (e.g. it gets evicted from the bfcache), the URL allows the client to still pretend it has the state, allowing the server to regenerate it based on the data in the URL. But why would you want to recreate the same document using a different page than the page that originally created the document. I.e. if I have a single page that I use to show various views, why would I all of a sudden want to use another page to render one of those views just because the user restarted the browser? Consider an AJAX version of Bugzilla. Each bug page has a different URL. As you navigate from bug to bug, the URL should change to point to the currently showing bug. But you want to do that without actually doing a reload (changing the Document object). Yes, this is a decent example. Or gmail could show a different URI depending on which mail you are currently reading, or which folder you are currently browsing. Also, the URL can be used when bookmarking the page. It could also be displayed in the location bar. Hmm.. bookmarking is indeed tricky. If a site really want to support bookmarking it seems like the best solution is to use the old hack of setting location.hash. The hash isn't sent to the server. Why would you want to send something to the server? The original page was loaded without that data being sent to the server. Again, fwiw, the URL parameter was added in response to author feedback to the effect that only having control over the hash was insufficient for what they wanted to do. Why? The argument against using the hash that I can see is that it has another semantic meaning. This causes troubles such as scrolling whenever it is set. (The Location object should not be updated, however.) Why not? Changing it would introduce a gratuitous difference between legacy UAs and UAs implementing this feature, as well as complexity that I'm not sure I really want to have to test. How exactly were you envisioning that people do fallback to legacy UAs? The solution that I can think of is to either set location = ... causing a reload on legacy UAs. Or you could set the hash which seems to work sufficiently well today. In both cases the Location changes. I would like to store the session states created using pushState on disk so that the state can be restored in the event of a crash or a restart. The only thing that would be needed to support this is that the 'data' object is a string rather than a generic object. This is because a generic object can't be serialized and saved to disk. Actually, what would be even better is if the API accepted a string or a JSON-ifyable object. That's what the URL is for. Then what is the point of the data object? It seems very bug prone that the data object is just dropped on the floor if the browser is restarted. I.e. we should recommend everyone not to use the data object (except for some sort of cache?) since it will always fail to work if the user restarts the browser. The data object is for when the page still exists, so that the state
Re: [whatwg] pushState
On Fri, 25 Jul 2008, Jonas Sicking wrote: FWIW, the title parameter was added in response to requests in feedback from application authors, who didn't want to change document.title for this. Requesting is easy. *Why* did they request this? Still seems like better UI design to have this affect the title. The title of my mail client changes to show what part of the UI I'm in. Currently it says whatwg for [EMAIL PROTECTED] indicating that i'm watching the whatwg folder on the [EMAIL PROTECTED] account. Well to reuse the GMail example again, you might have entries like (in reverse chronological order, current entry at the top): GMail - in:spam - checked all unread GMail - in:spam - unchecked all GMail - in:spam - checked 2 messages GMail - in:spam GMail - Inbox ...while the actual titles were (in the same order): GMail - Search - in:spam GMail - Search - in:spam GMail - Search - in:spam GMail - Search - in:spam GMail - Inbox This seems like a reasonable thing to support. Also, the URL can be used when bookmarking the page. It could also be displayed in the location bar. Hmm.. bookmarking is indeed tricky. If a site really want to support bookmarking it seems like the best solution is to use the old hack of setting location.hash. The hash isn't sent to the server. Why would you want to send something to the server? Well again, consider Bugzilla -- Bugzilla knows how to generate a bug page if you go to that URL. You don't go to: http://bugzilla.mozilla.org/#bug2 ...and have AJAX fetch down the bug data. Again, fwiw, the URL parameter was added in response to author feedback to the effect that only having control over the hash was insufficient for what they wanted to do. Why? So they can do what Bugzilla does, for instance. (The Location object should not be updated, however.) Changing it would introduce a gratuitous difference between legacy UAs and UAs implementing this feature, as well as complexity that I'm not sure I really want to have to test. How exactly were you envisioning that people do fallback to legacy UAs? There are already libraries that emulate this behaviour using nested iframes. The idea would be to simply have those libraries use pushState() if it was available instead. We wouldn't want unrelated things like the Location object changing just because they used the HTML5 feature, something which to the user of the library is an implementation detail. (See, e.g., how Google Maps stores state in the back button without reloading today.) The data object is for when the page still exists, so that the state can be updated on the fly, e.g. bringing back the exact same video element to the front, or whatever. You can still do this, it's just that we won't encourage it using an API. You can just store your video or whatnot in some cache in some global object. You could even store it in an array and store the index of that array in the stored data object. Storing objects in the history state isn't going to extend the lifetime past that of the Document anyway. The UA is going to want to tear down all stored objects when tearing down the Document since otherwise its very likely that those objects would keep the Document alive, if nothing else through the JS __parent__. This actually means that even when not talking about a restart, in order to better support long history chains where the Document is likely to be evicted from the fastback cache, we should enforce that the data objects be serializable (JSON-able). I don't understand what you are proposing here. Right now, when the Document is discarded, so are all the objects that were pushed using pushState(), as well as all the entries that don't have an explicit URL. You are saying that over a restart you want to preserve even the entries that don't have a URL? That doesn't make sense to me, after all, all the data those pages had loaded into RAM is gone now, they'd need to resinstantiate all the objects. But all those complex cases will fail on a browser restart. It is much better if we encourage people to write stable code. The original feature wasn't expected to work at all across a browser restart. Well, consider it requested ;) Right, that's what the URL parameter is for. Originally there was just the data argument, and no URL or title. We added URL to support the restart and bookmarking cases. To use GMail as an example again, one might want to pushState() for every change of selected e-mails, but only pushState() with a URL when the search query changes. Seems ok to me. So, the same applies to restarts. You'd want the history of search query changes to survive, but the individual checks of the checkboxes don't need to -- and tracking them would in any case be way harder since the original DOM is gone by that point.
Re: [whatwg] pushState
So to back up. There are a few things that are important to me: 1. The session history (SH) entries created in this way should act as much like normal SH entries as possible to the user. I.e. the user doesn't care if clicking what looks like a link results in a navigation or a .pushState call. 2. That this API allows pages to be written that survives a browser restart. This is to prevent data loss in case of crash, and to increase chances that users install security updates which require restart as soon as possible. 3. That the API encourages bug-free pages. I.e. pages that use the API 'correctly'. Just 1 in itself means that we can't just kill SH entries just because the Document they were created from goes away from fastback. If I browse away from a gmail and see 5 pages in my SH list then I would be very disappointed if those 5 pages just disappeared because I happened to be browsing around in another window which ate up the fastback cache. Similarly, a mobile device might not have a fastback cache at all. It would look very strange if while i'm staying on the gmail site i'm able to go 'back' to what to me looks like various different pages. But as soon as i go to some other site, I loose all those pages and can only go back directly to the first gmail page. So we must definitely store the pushed SH data in such a way that if the Document is recreated the data survives. This applies whether the URL of my browser changes or not while I'm doing this browsing. The rendering changing is more important than the URL changing for a user. So what I think we should do is to enforce that 'data' is a JSON serializable object. When a Document is destroyed (due to eviction from the fastback cache or due to not being cachable) we don't touch the SH entries associated with that document. When entering a SH state for which a Document has been destroyed, we load the URL associated with that SH entry. After the 'load' event for the Document has fired, and if a data object was provided in the pushState call for the SH entry, we fire a PopStateEvent event containing the data stored for the object. The same thing happens if the user clicks the reload button while on an SH entry created using pushState. The URL for that entry is loaded and after the 'load' event has fired, if a data object was provided during the pushState call, a PopStateEvent is fired with that data. To minimize the difference between when a SH entry is recovered from the fastback cache, compared to when the document is reparsed, the Location object should be changed to reflect the new URL whenever pushState is called with a url. The advantage of changing the Location object is that this makes the page behave the same no matter of if it has been reloaded or not. Setting the Location objects value will cause reloading vs. scrolling vs. do nothing in the same cases. Similarly reading the Location will return the same thing no matter of if there has been a reload or not. Yes, this is different from how legacy browsers behave. However the whole point of this API is to improve on the current iframe hacks. If we didn't there would be no point in adding a new API as it wouldn't be worth the code fork for users. Reloads mostly don't work with the iframe hack anyway so you'll end up with vastly different behavior no matter what. And if we're not considering the reload case then the hashchanged event should be enough. This isn't a big deal though as far as I can think of. Only if your application runs inside someone elses iframe and that outer app is intimately interacting with you I can see that it makes a difference. This doesn't seem common enough that we should prioritize for it. / Jonas
[whatwg] pushstate + hashchanged
Pushstate looks great, but with it a new need arises. When the user changes the path in the locationbar, reload is triggered. It should not, as to match the behavior of the hash change. Instead, just an event should be dispatched. Something like hashchanged or popstate event, I'm not sure. Which portion of the path should cause reload and which should not ('cause is supposedly managed by javasript) would be configurable by a new property, e.g. something like document.basePath. So what do you think? Ivan Vim