javascriptbrowser-historypushstatejquery-bbq

How to replace the location hash and only keep the last history entry?


I'm using the jQuery BBQ plug-in to track the users progress through the page. However, I only want to create 1 additional entry in the user's history, not one for every hash change.

I've tried the jQuery.bbq.pushState and merge_mode methods, without success: New history entries are still added:

jQuery.bbq.pushState({ sort: encodeURIComponent(sort) });

I have also tried location.replace(), but that doesn't work for Safari 5.1.2.

location.replace('#' + encodeURIComponent(sort))

What's the cross-browser solution to modify the hash, without adding too much entries to the history?


Solution

  • First, I show the definition of function replaceHash, which accepts only one argument: The new location hash. A detailed explanation of the logic can be found at the bottom of the answer.

    Code:

    // Should be executed BEFORE any hash change has occurred.
    (function(namespace) { // Closure to protect local variable "var hash"
        if ('replaceState' in history) { // Yay, supported!
            namespace.replaceHash = function(newhash) {
                if ((''+newhash).charAt(0) !== '#') newhash = '#' + newhash;
                history.replaceState('', '', newhash);
            }
        } else {
            var hash = location.hash;
            namespace.replaceHash = function(newhash) {
                if (location.hash !== hash) history.back();
                location.hash = newhash;
            };
        }
    })(window);
    // This function can be namespaced. In this example, we define it on window:
    window.replaceHash('Newhashvariable');
    

    Function logic