Reputation: 27227
Consider a page that contains only this script tag:
<script type="text/javascript">
window.location.hash = 'testing';
window.history.back();
</script>
If you go to google.com, then load that page, you'll see the hash update in the address bar, but then the page goes back to Google! I expect it to just remove the #testing
hash.
If I wrap it in a long timeout, it works as expected:
<script type="text/javascript">
setTimeout(function () {
window.location.hash = 'testing';
window.history.back();
}, 1000);
</script>
The address bar briefly flashes the #testing
hash, and then it is removed.
This means that, at some point in time, changes to the location.hash are propagated to the history api. There must be some event that fires when this behavior changes.
I've looked through the list of events on mdn and found these:
pageshow
: The pageshow event is fired when a session history entry is being traversed to. (This includes back/forward as well as initial page-showing after the onload event.)
load
: The load event is fired when a resource and its dependent resources have finished loading.
Neither of these events fix the issue. I tried:
<script type="text/javascript">
window.addEventListener('pageshow', function () {
window.location.hash = 'testing';
window.history.back();
}, false);
</script>
and the same with the load
event. The address bar flashes the #testing
hash, then the browser returns to the previous page.
How can I detect if modifying location.hash
is safe to do?
Upvotes: 2
Views: 827
Reputation: 27227
It seems that the load
event is on the right track, but with a slight twist. The history api picks up the change one tick after the load event.
That is, this code is problematic:
<script type="text/javascript">
window.addEventListener('load', function () {
window.location.hash = 'testing';
window.history.back();
}, false);
</script>
But this code correctly removes the hash:
<script type="text/javascript">
window.addEventListener('load', function () {
setTimeout(function () {
window.location.hash = 'testing';
window.history.back();
}, 1);
}, false);
</script>
I am not sure why this is, and I can not find any spec that states this should be the case, but this is what I found after some trial and error.
2023 update: The behavior still exists as of Chrome v111 and Safari v16.3, but is not reproducible on Firefox v111.
Upvotes: 1