ubiquibacon
ubiquibacon

Reputation: 10667

Setting window.location.hash does not work with back button as of Chrome 47

I have a standalone HTML file (not hosted) which uses UI Layout and Fancytree. I have tried hosting using Python's SimpleHTTPServer and I have the same problem. The tree is used for navigation, so its nodes are all anchor links. When an anchor link is clicked the goToLink function is called and the main UI Layout pane does an animated scroll to the correct anchor and the link that was clicked is added to the browser's history so the user can make use of the back button. This worked as desired until Chrome version 47. I have tried several variations of the code below, but I always get the same result when the back button is pressed. That is, the URL changes in the address bar, but the page does not jump back to the correct anchor. This is also a problem in Firefox but I'm not sure what version of Firefox it got broken in. I don't care about IE.

function goToLink(link) {
    if(link.slice(0, 1) != "#") {
        link = "#" + link;
    }

    var a = $('[name="' + link.slice(1) + '"]');
    var parent = a.parent();
    var pane = a.closest('.ui-layout-center');
    var aTop = a.offset().top;
    var paneTop = pane.offset().top;

    pane.animate({scrollTop: '+=' + (aTop - paneTop) + "px"}, 1000, "linear");
    var currentLocation = pane.scrollTop();
    window.location.hash = link;
    pane.scrollTop(currentLocation);
}

Upvotes: 0

Views: 1709

Answers (2)

OZZIE
OZZIE

Reputation: 7348

It's quite strange that they've implemented it like this but the solution is quite easy, just add this on inital load.

window.history.replaceState({}, document.title, window.location.href);

Upvotes: 1

ubiquibacon
ubiquibacon

Reputation: 10667

It looks like this problem is related to Chrome's recently introduced Scroll Restoration. I got around the problem by detecting that feature and tracking hash changes. This also fixes the issue in Firefox:

var hashAlreadyChanged = false;
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
var goToLinkOnHashChange = 'scrollRestoration' in history || isFirefox;

$(window).on('hashchange', function() {
    if(goToLinkOnHashChange) {
        goToLink(window.location.hash);
        hashAlreadyChanged = false;
    }
});

function goToLink(link) {
    if(link.slice(0, 1) != "#") {
        link = "#" + link;
    }

    if(!hashAlreadyChanged) {
        hashAlreadyChanged = goToLinkOnHashChange;

        var aName = isFirefox ? decodeURI(link) : link; // Firefox auto encodes the URL so I decode to get the correct "a" tag name
        var a = $('[name="' + aName.slice(1) + '"]');
        var pane = a.closest('.ui-layout-center');
        var aTop = a.offset().top;
        var paneTop = pane.offset().top;

        pane.animate({scrollTop: '+=' + (aTop - paneTop) + "px"}, 1000, "linear");

        var currentLocation = pane.scrollTop();
        window.location.hash = link;
        pane.scrollTop(currentLocation);
    }
}

Upvotes: 0

Related Questions