Search code examples
javascripthtmlpushstatehtml5-history

History pushed state is not in standalone location.hash or location.href but is in Location object itself


Can anyone explain this behavior? I push history state using history.pushState(null, null, '#test');. Then when trying to get state URL in the listener function (didn't find a better way how to listen to pushState changes) using console.log(window.location.hash), it returns empty string, #test hash. console.log(window.location.href) returns whole URL without hash #test too but console.log(window.location) returns Location object where the hash is in both href and hash properties. Why is that and how can I get the URL of pushed state?

        (function(history){
            var pushState = history.pushState;
            history.pushState = function(state) {
                if (typeof history.onpushstate == "function") {
                    history.onpushstate({state: state});
                }
                console.log(window.location.hash);
                console.log(window.location.href);
                console.log(window.location);
                return pushState.apply(history, arguments);
            }
        })(window.history);

        history.pushState(null, null, '#test');

Solution

  • This is because you are logging the variables before you actually set the new state. The reason you can see the updated properties in the object, because it logs a reference to the object, rather than a copy of the object when it was logged. Your monkey patch does not call the original pushState function until this line.

    return pushState.apply(history, arguments);
    

    To work around this, you could simple call the function before logging, then return the response afterwards.

    (function(history){
        var pushState = history.pushState;
        history.pushState = function(state) {
            if (typeof history.onpushstate == "function") {
                history.onpushstate({state: state});
            }
            var r = pushState.apply(history, arguments);
            console.log(window.location.hash);
            console.log(window.location.href);
            console.log(window.location);
            return r;
        }
    })(window.history);
    
    history.pushState(null, null, '#test');