history.js
history.js copied to clipboard
State does not get pushed if only the URL changes to an empty string
If you do, for example:
pushState({}, 'title', '?foo=bar'); pushState({}, 'title', '');
The second call to pushState is ignored because in History.normalizeState() it does this:
newState.url = History.getFullUrl(oldState.url?decodeURIComponent(oldState.url):(document.URL||document.location.href));
The assumption here seems to be that oldState.url being false-like means the caller didn't want to change URLs (?)
In any case, I think the test needs to be smarter somehow, perhaps (oldState.url || oldState.url === '') to allow an empty string to be considered a specified URL whereas other false-like values like null, undefined, and false would be treated as a missing value.
As a workaround, I've changed my call to pushState to pass "url || '/'" which also solves the problem for me. However, this was a hard-to-find bug for me so I'd recommend fixing it for the benefit of those who come after.
I can confirm it also doesn't work with
replaceState({}, 'title', '')!
It would be great to just wipe the previous changes of the url away. I cannot quite figure out how dobesv solved the issue. Will you go into more detail?
To me it seems right now I have to count all the changes in the history and then apply some History.back() to get back to a blank state?
@medienprodukt My workaround was to pass '/' instead of an empty string, if the new URL is supposed to be blank. The end result is more or less the same, as the URL will have the path and query parameters removed.
It seems '/' only works for the root of a site, if you call '/' from
foobar.com/foo/bar
the url jumps to the root of the site
foobar.com/
For now I changed my code to
replaceState({}, 'title', History.getBaseUrl())
but that only works on html5 browsers :/
Ah, what did you want it to do when you passed an empty string for the url? I expected it to go to the root of the site, and I believe that is what it does if some other part of the state has changed. If you just wanted to strip off the query string I think you would have to do that manually by passing a URL with everything after the first '?' or '#' removed.
On Sat, Dec 17, 2011 at 12:46 AM, Medienprodukt < [email protected]
wrote:
It seems '/' only works for the root of a site, if you call '/' from
foobar.com/foo/bar
the url jumps to the root of the site
foobar.com/
For now I changed my code to
History.getBaseUrl()
but that only works on html5 browsers :/
Reply to this email directly or view it on GitHub: https://github.com/balupton/history.js/issues/131#issuecomment-3179476
I thought
History.replaceState(null, null, History.getBaseUrl());
would take me back to the initial state of my url
foobar.com/foo/bar/
like it does in all the HTML5 browsers. But in IE8 the result is
foobar.com/foo/bar/#./
Ah I see, seems to be a quirk of the HTML4 support, I think I have seen this mentioned in other issues but I'm not sure whether it has an issue of its own. Ideally it would remove the #./ from the end, I think.
+1
Use "./":
pushState({}, 'title', './');