history.js icon indicating copy to clipboard operation
history.js copied to clipboard

State does not get pushed if only the URL changes to an empty string

Open dobesv opened this issue 14 years ago • 8 comments

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.

dobesv avatar Nov 24 '11 11:11 dobesv

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 avatar Dec 15 '11 17:12 medienprodukt

@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.

dobesv avatar Dec 16 '11 12:12 dobesv

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 :/

medienprodukt avatar Dec 16 '11 16:12 medienprodukt

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

dobesv avatar Dec 17 '11 08:12 dobesv

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/#./

cocomo avatar Jan 04 '12 15:01 cocomo

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.

dobesv avatar Jan 11 '12 07:01 dobesv

+1

jpmckinney avatar Mar 09 '13 23:03 jpmckinney

Use "./":

pushState({}, 'title', './');

Saxintosh avatar Feb 12 '21 14:02 Saxintosh