Version 2.0 – HTML5 History
We’ve mentioned before that FixMyStreet is built on a progressively-enhanced base, a concept explained neatly in a nice blog post from the UK government.
This means that e.g. the slippy map is, underneath it all, an old-style server-side image map that works out where you click; URLs are all shareable and pages are functional even if JavaScript is not available; the front page loads quickly and doesn’t need to preload an entire application.
None of this means that we don’t use or like JavaScript, however. This post is about adding JavaScript to FixMyStreet to provide a quicker experience to users looking at reports on our map.
When viewing a list of reports on FixMyStreet, you might want to look at a few reports one after the other, much as you can on a Google Maps or OpenStreetMap results screen.
So now, when you click a report in the list or a pin on the map, the report page is pulled in via JavaScript. This updates the page, pin and URL in situ, rather than loading a new page. Other pins remain visible, plus the page feels (and probably is) a bit quicker as the page header doesn’t reload, and it is easy to switch back to the list view.
This feature uses HTML5’s History API, ie. pushState
and popState
, to
update the URL as the page changes. That means that when you share it,
the page that loads will always be the one that the user intended it to be.
This improvement did not come without problems, however. Overriding the browser’s own behaviour when it comes to history and navigation means you have to think carefully, and I’m sure we’ll need to make further refinements to ensure that everything works as the user would expect.
There were small issues: for example, pushState
stores the document title at
the point when it’s called, for the ‘Back’ button list, meaning we had to make
sure any title change happened after that. Some browsers have a popstate
on
page load, which can cause an issue if you assume it’s only fired due to
history events.
There was the complication of needing to tell the difference between someone
clicking back to the ‘initial state’ of the page, and an internal hashchange or
other less crucial event – as well as using a replaceState
on page
load, we store the original URL and title for use in such a situation.
Then we forgot that the code would be running on /reports
lists as well as
/around
which led to some confusion until we realised what was happening! And
of course, you have to make sure everything JavaScript-wise is set up
appropriately for content brought in via JavaScript.
We also used pushState
in the new report process, to update the URL as you
select the report’s location, and on list pages when you select one of the
filters or sort. This has worked well, and is certainly much more preferable to
the ‘hash-bang’ technique used by some sites in previous years (and still now),
which is reliant on JavaScript functioning.
If you have any questions, or problems installing the code, please do get in touch, or post on our mailing list.