HTML5 History needs another event

I love the HTML5 History API, it makes developing applications with a consistent URL scheme across server and client super simple, however it doesn't come without its problems.

When developing the [LeviRoutes URL routing](https://github.com/PaulKinlan/leviroutes) framework it became obvious that we need some changes to the specification as-is. The [Mozilla documentation](https://developer.mozilla.org/en/DOM/window.onpopstate) reports that onpopstate is called whenever the history object changes, unfortunately this is not the case, and is not the case with the spec either, the [HTML5 Spec](http://www.w3.org/TR/html5/history.html#event-popstate) indicates: “The popstate event is fired in certain cases when navigating to a session history entry.”, which you can logically assume to be only on a forward, backwards navigation, not a replaceState or pushState.

This might sound odd. There is no mechanism to detect change in url afterit changes. You get notification via onpopstate when the user navigates forwards or backwards through your application, but not actually when it changes. This is apposed to onhashchange which does fire when the document fragment changes.

This causes us problems.

LeviRoutes listens to changes in your URL, it allows you to build applications that are responsive to the current URL, and are decoupled from navigation. So rather than have your code littered with 'if(url == '/“) { doA(); } if (url == ”/categories") { doB(); } you can now specify:

var app = routes();
app.get("/", doA);
app.get("/categories", doB);

Simple right?

It would be excellent if it was that simple, but it is not. We don't know when the URL changes via pushState. This forces us o bind our logic in our controller to call the same code that LeviRoutes would call when it detects a change in URL via normal navigation.

Now I have to bastardise my code:

var app = routes();
app.get("/", doA);
app.get("/categories", doB);

.....
function gotoA () {
    history.pushState({}, "A", /);
    doA();
}
...

Pretty messy right?

I would love to see an event 'onstatechanged' (or perhaps, onpushstate and onreplacestate) triggered when the user pushes or replaces state on to the history object so that I can capture the code and return to my simple routing logic.

var app = routes();
app.get("/", doA);
app.get("/categories", doB);

function gotoA () {
    history.pushState({}, "A", /);
}

I am not the only person asking for this: [http://www.google.com/search?q=onpushstate](http://www.google.com/search?q=onpushstate)

So, how am I going to solve this problem? I am going to wrap the History API and proxy pushState to call the natural pushState and also fire a new custom event. Hmph :\

About Me: Paul Kinlan

I lead the Chrome Developer Relations team at Google.

We want people to have the best experience possible on the web without having to install a native app or produce content in a walled garden.

Our team tries to make it easier for developers to build on the web by supporting every Chrome release, creating great content to support developers on web.dev, contributing to MDN, helping to improve browser compatibility, and some of the best developer tools like Lighthouse, Workbox, Squoosh to name just a few.