How can I update window.location.hash without jumping the document?

Viewed 183441

I have a sliding panel set up on my website.

When it finished animating, I set the hash like so

function() {
   window.location.hash = id;
}

(this is a callback, and the id is assigned earlier).

This works good, to allow the user to bookmark the panel, and also for the non JavaScript version to work.

However, when I update the hash, the browser jumps to the location. I guess this is expected behaviour.

My question is: how can I prevent this? I.e. how can I change the window's hash, but not have the browser scroll to the element if the hash exists? Some sort of event.preventDefault() sort of thing?

I'm using jQuery 1.4 and the scrollTo plugin.

Many thanks!

Update

Here is the code that changes the panel.

$('#something a').click(function(event) {
    event.preventDefault();
    var link = $(this);
    var id = link[0].hash;

    $('#slider').scrollTo(id, 800, {
        onAfter: function() {

            link.parents('li').siblings().removeClass('active');
            link.parent().addClass('active');
            window.location.hash = id;

            }
    });
});
9 Answers

This solution worked for me.

The problem with setting location.hash is that the page will jump to that id if it's found on the page.

The problem with window.history.pushState is that it adds an entry to the history for each tab the user clicks. Then when the user clicks the back button, they go to the previous tab. (this may or may not be what you want. it was not what I wanted).

For me, replaceState was the better option in that it only replaces the current history, so when the user clicks the back button, they go to the previous page.

$('#tab-selector').tabs({
  activate: function(e, ui) {
    window.history.replaceState(null, null, ui.newPanel.selector);
  }
});

Check out the History API docs on MDN.

This solution worked for me

// store the currently selected tab in the hash value
    if(history.pushState) {
        window.history.pushState(null, null, '#' + id);
    }
    else {
        window.location.hash = id;
    }

// on load of the page: switch to the currently selected tab
var hash = window.location.hash;
$('#myTab a[href="' + hash + '"]').tab('show');

And my full js code is

$('#myTab a').click(function(e) {
  e.preventDefault();
  $(this).tab('show');
});

// store the currently selected tab in the hash value
$("ul.nav-tabs > li > a").on("shown.bs.tab", function(e) {
  var id = $(e.target).attr("href").substr(1);
    if(history.pushState) {
        window.history.pushState(null, null, '#' + id);
    }
    else {
        window.location.hash = id;
    }
   // window.location.hash = '#!' + id;
});

// on load of the page: switch to the currently selected tab
var hash = window.location.hash;
// console.log(hash);
$('#myTab a[href="' + hash + '"]').tab('show');

When using laravel framework, I had some issues with using a route->back() function since it erased my hash. In order to keep my hash, I created a simple function:

$(function() {   
    if (localStorage.getItem("hash")    ){
     location.hash = localStorage.getItem("hash");
    }
}); 

and I set it in my other JS function like this:

localStorage.setItem("hash", myvalue);

You can name your local storage values any way you like; mine named hash.

Therefore, if the hash is set on PAGE1 and then you navigate to PAGE2; the hash will be recreated on PAGE1 when you click Back on PAGE2.

Related