0

I am trying to distinguish between two types of URL Changes.

Basically with pushstate it is possible to move from http://example.com to http://example.com/account without reloading the page (here is an example).

It is possible to detect these changes with the following trick (taken from [here]( How to detect URL change in JavaScript)):

/* Add a locationstorage event in the window */
history.pushState = ( f => function pushState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('pushState'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.pushState);

history.replaceState = ( f => function replaceState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('replaceState'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.replaceState);

window.addEventListener('popstate',()=>{
    window.dispatchEvent(new Event('locationchange'))
});

// Capture the locationchange event
window.addEventListener('locationchange', function(){
    console.log('location changed!');
});

Though, I realized that it also capture Hash URL changes, e.g. http://example.com#about. I know that Hash URL changes can be captured with this:

$(window).bind('hashchange', function() {
 /* things */
});

My problem is that hash changes also trigger a popstate (in the history) (see here).

How would I go about distinguishing these two types of events?

toto_tico
  • 17,977
  • 9
  • 97
  • 116

1 Answers1

0

I was worried to have to depend on a regular expression to obtain the hash, but I just realized that the Location object already parses the hash from the URL.

All i needed to do was to caputer the hash from the location before and after the event (and keep it updated);

So, introduce a variable with the current location:

current_hash = window.location.hash;

And use it to distinguish the type of URL change (keep it updated):

window.addEventListener('popstate', (ev) => {
    if (ev.target.location.hash == current_hash){
       window.dispatchEvent(new Event('locationchange'));
    } else {
      current_hash = ev.target.location.hash;
    }
});

Full example

# variable that keeps the current hash
current_hash = window.location.hash;

history.pushState = ( f => function pushState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('pushState'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.pushState);

history.replaceState = ( f => function replaceState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('replaceState'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.replaceState);

window.addEventListener('popstate', (ev) => {
    # use it to distinguish the event
    if (ev.target.location.hash == current_hash){
       window.dispatchEvent(new Event('locationchange'));
    } else {
      # keep current hash updated
      current_hash = ev.target.location.hash;
    }
 });

 window.addEventListener('locationchange', function(event){
   console.log('location changed!');
 })
toto_tico
  • 17,977
  • 9
  • 97
  • 116