- From: Nathan Hammond <nathan@nathanhammond.com>
- Date: Wed, 5 Aug 2009 01:18:22 -0400
Ian, Thanks for the comments. I've simply omitted pieces that I feel like are completely addressed. For all of those: Yes, I agree, right, right, great, and perfect. Thanks for clarifying and answering silly questions. For the rest, see below. > On Aug 4, 2009, at 9:29 PM, Ian Hickson wrote: >> On Wed, 29 Jul 2009, Nathan Hammond wrote: >> >> Possible Action Items >> 1. Specify the order in which history related events are triggered. >> >> In what order would one expect the events triggered by >> window.history.pushState({}, "Title", "#newhash")? > > No events are triggered by doing that. With my new understanding of pushState, not triggering popstate makes sense. With regards to pushState not triggering a hashchange event, I like it, but I do want to be absolutely sure that all implementers get this right. So, could we clarify this in the spec? Right now I think that the spec could be read where since it adjusts the document's current address it might should cause a hashchange event. Providing this specific example would do the trick. Related, is window.location.hash = "newhash"; supposed to trigger a hashchange event? (Is this specified? I couldn't find it.) I do believe it does in IE8, but I don't have IE8 available to me at this moment to check. >> 2. Specify a method to allow access to the history stack. (At least >> readable within the context of same-origin, possibly mutable.) >> >> This would allow for understanding on the client side of a user's >> path >> through the site, even after navigating away from the page. If this >> is >> not implemented the absolute first thing I will be implementing is a >> method to track this information, a rather large duplication of >> effort >> for something that could easily be made available. This would >> involve a >> something like currentstate = { _previous: currentstate, title: >> window.title, newval: true }; plus a form-based storage mechanism to >> repopulate state in case the user exits on a page which they manually >> changed the hash to get to (which would not have access to the data >> object upon revisiting later since there wouldn't be one stored with >> that history state). >> >> I'm aware of the privacy ramifications, but at the same time, I'm >> going >> to be exposing those exact same concerns with the above method. > > It turns out to be quite complex to expose this in the API currently, > because the History object exposes a mix of all the various frames at > once, and you can get to the History object of cross-origin frames, > and > there's some other legacy baggage here also (e.g. history.length). > > Since it's not entirely clear what the use case is, and since you > can do > it to some extent already using onload, onhashchange, and > onpopstate, I'd > rather just let authors reimplement this themselves at this point, and > maybe revisit this in a future version. Complexity. Bah! (Then again, you don't have to tell me.) The use case I find is pretty simple: in the event that there are two separate ways to get to a specific page in the app I need to know how the person got there. Or this could be used to provide content tailored specifically to that user based upon their history (whether suggestions, ads, or help text). Really though, this point is far less critical (as it is easy enough to handle in client code) and does greatly increase the complexity for getting all implementers on board. If this *isn't* implemented however, the point below becomes more critical for being able to successfully track state in client code... >> 3. Specify a method to modify the current history state without >> adding a >> new history point. > > Assuming you don't mind causing the page to reload, you can use > history.replace(). I'm not sure what it would mean to replace the > history > state without changing the Document or anything, though. > >> This would alleviate the need for the (incredibly brittle) form-based >> storage mechanism I describe above. > > Can you use sessionStorage for this? I should have stated this one with a goal: the ability to ensure that the popstate event always fires with a full understanding of the (app/ page) state when navigating through history. This would be lost when a user manually changes the hash. With that as my goal, history.replace does not achieve what I am trying to accomplish. Neither does pushState without a URL as that still registers a new history point. Any other techniques for remembering data other than this would still be a hack because, in and of itself, the data stored are not uniquely tied to a particular history state. In my semi-professional opinion form "storage" is really more appropriate for this task as it is correctly mapped to the document object on which the data was entered. Using sessionStorage I have the additional task of mapping the stored series of states to a particular visit of the (app/page) if the user visits the site again after navigating away: example.com -> whatwg.com -> example.com (Use case is the game idea I'm toying with that uses state paired with CSS3's :target pseudo-class for a sort of battleship meets minesweeper thing/demo ... I haven't completely worked out the mechanic but I'm planning on turning it into a history demo.) >> 4. Specify additional properties on the hashchange event. >> >> Lots of possible useful information with the number one most >> important >> being the new hash that triggered the event to prevent race >> conditions >> reading window.location.hash. Other fun things that are a bit more >> pie >> in the sky: the previous hash and knowledge of how it was triggered >> (manually? pushState? window.location.hash = ? window.location.href = >> ?). > > What are the use cases? My primary concern here is based upon my experience with having to poll to emulate hashchange. In this scenario it is quite possible to have two unique actions which are only registered as one (depending upon if the hash checking is reactive and responds to a new hash or proactive and sets the hash as part of the action and notifies the listener to ignore). Thinking about it more you can almost get rid of the race condition since hashchange events will always be triggered serially by monitoring from the beginning the current value. This value would only need to be updated when a hashchange event occurs-- but that event must identify the updated value of the hash that triggered the hashchange event. Otherwise there is some possibility of: 1. Navigation request. 2. Script loads, stores initial hash. 3. Hash changes and fires hashchange event 1. 4. Hash changes and fires hashchange event 2. (~12ms apart is about the limit) 5. hashchange event 1 is processed, reading location.hash reflects the value from event2. Sure, infinitesimally small chance of triggering it, but it would not be fun if it did. As to use cases for more information, knowing how the event was triggered would allow for handling it differently (human- triggered, need to respond, programmatic, I've already handled it). >> On Thu, 30 Jul 2009, Nathan Hammond wrote: >> >> 2. Clarify that pushState() does not cause navigation. >> >> I read the spec quite a few times and still got this wrong, >> apparently. >> Making this completely clear would not hurt. > > Could you elaborate on what led you to this conclusion? Absolutely: my previous "understanding" and misconceptions of how this is exactly handled behind the scenes. Maybe it was simply my familiarity with having to use the hash that made the other seem completely illogical, I've spent many many hours trying to emulate history management with browser features that already exist. When prepping to send comments I read pieces of the spec as they applied many times, and things that were only tangentially related I didn't necessarily read as carefully. The way it appears to me now, re- reading, the spec is written in a way that it only identifies exactly what is to be done, and if not explicitly mentioned no other actions are taken. Reading the spec in "fill-in-the-blank" mode, which is how I did originally, without my new insight into how it appears to be written and knowledge of how things work right now had me jumping to conclusions about what is supposed to happen. So I'd say that nothing in particular led me there, I simply wasn't steered away. Looking back at my comments it becomes clear that most of my concerns it turns out aren't directly related to the spec and are more closely things that were simply not completely clear to me. And maybe that is an issue we want to address, adding a few statements as to what pieces of the spec do not mean would I think go a long way in helping those who are interested but a little less immediately involved day-to-day (implementers coming to a section for the first time). Best, Nathan
Received on Tuesday, 4 August 2009 22:18:22 UTC