history.js
history.js copied to clipboard
HTML5: statechange not triggered when navigating back to a hashed URL
If you load a URL that contains a hash
http://localhost/test#abc
And then you navigate to
http://localhost/test?q=hello
When you click on the browser's Back button, the statechange handler is not triggerred causing the content for ?q=hello to still be displayed. I do a History.replaceState on page load to set the default state so I expect the state data that was initially set to be used in the statechange handler. But the handler is not triggerred at all. Note that I don't include the hash when setting the default state.
Without the hash, everything works as expected.
Is this a bug or a limitation in the HTML5 history.js?
I tried this fix and setting History.options.transformHash to false resolves the issue.
https://github.com/christanto/history.js/commit/b78af84fc2b6b5da573e5ee0bd72f4213e36bb18
I hope this gets merged to the master branch asap.
Sorry, this is not fixed yet. See my comment at https://github.com/christanto/history.js/commit/b78af84fc2b6b5da573e5ee0bd72f4213e36bb18#commitcomment-3221379
I don't think http://localhost/test?q=hello to http://localhost/test#abc is a state change, you're still on http://localhost/test so the event isn't triggered.
No. I pushState when querystrings are added or changed and I replaceState on page load.
I'm also experiencing this issue when I navigate from one URL to a totally different URL that happens to have a hash. For example, when I navigate from http://localhost/news to http://localhost/news/myarticle#comments, a state change is not fired.
Same here.
E.g. from /data/ to /item/1/comments#c5
State is pushed but no statechange raised.
A very unfortunate issue here.
Managed to find a less than ideal solution by binding actions to 'popstate' and 'statechange'. This means its triggered twice in most cases but there's some booleans to prevent it actually performing all the actions more than once.
I haven't yet tested how this affects non-html4 browsers but hopefully helps others and would appreciate any feedback :)
History.Adapter.bind(window, 'popstate statechange', function() { // history.js suggests statechange but it has a bug with urls with hashes not firing statechange
var newLocation = getLocation(); // location.pathname + location.search ...
if(newLocation != currentLocation) { // prevent firing multiple times, on hash changes, or replaceState()...
if (!anchorClick && !search && !state_change_animation_in_progress) { // if navigating via the history...
var State = History.getState(),
prevState = History.getStateByIndex(History.getCurrentIndex()-1);
if (State.data.index < prevState.data.index) {
historyBack = true;
}
historyIndex = State.data.index; // update index tracker
ajax_this(window.location.pathname); // gets content at the current address since the statechange already occurred...
}
anchorClick = false;
search = false;
}
currentLocation = newLocation;
});
+1
+1
FYI: repo isn't maintained according to #390. You're better off finding another solution or managing it yourself.
+1