Is it possible to remove the hash from window.location
without causing the page to jump-scroll to the top? I need to be able to modify the hash without causing
window.location's hash property is stupid in a couple of ways. This is one of them; the other is that is has different get and set values:
window.location.hash = "hello"; // url now reads *.com#hello
alert(window.location.hash); // shows "#hello", which is NOT what I set.
window.location.hash = window.location.hash; // url now reads *.com##hello
Note that setting the hash property to '' removes the hash mark too; that's what redirects the page. To set the value of the hash part of the url to '', leaving the hash mark and therefore not refreshing, write this:
window.location.href = window.location.href.replace(/#.*$/, '#');
There is no way to completely remove the hash mark once set without refreshing the page.
UPDATE 2012:
As Blazemonger and thinkdj have pointed out, technology has improved. Some browsers do allow you to clear that hashtag, but some do not. To support both, try something like:
if ( window.history && window.history.pushState ) {
window.history.pushState('', '', window.location.pathname)
} else {
window.location.href = window.location.href.replace(/#.*$/, '#');
}
I believe if you just put in a dummy hash it won't scroll as there is no match to scroll to.
<a href="#A4J2S9F7">No jumping</a>
or
<a href="#_">No jumping</a>
"#"
by itself is equivalent to "_top"
thus causes a scroll to the top of the page
I use the following on a few sites, NO PAGE JUMPS!
Nice clean address bar for HTML5 friendly browsers, and just a # for older browsers.
$('#logo a').click(function(e){
window.location.hash = ''; // for older browsers, leaves a # behind
history.pushState('', document.title, window.location.pathname); // nice and clean
e.preventDefault(); // no page reload
});
Hope this helps
html
<div class="tabs">
<ul>
<li><a href="#content1">Tab 1</a></li>
<li><a href="#content2">Tab 2</a></li>
<li><a href="#content3">Tab 3</a></li>
</ul>
</div>
<div class="content content1">
<p>1. Content goes here</p>
</div>
<div class="content content2">
<p>2. Content goes here</p>
</div>
<div class="content content3">
<p>3. Content goes here</p>
</div>
js
function tabs(){
$(".content").hide();
if (location.hash !== "") {
$('.tabs ul li:has(a[href="' + location.hash + '"])').addClass("active");
var hash = window.location.hash.substr(1);
var contentClass = "." + hash;
$(contentClass).fadeIn();
} else {
$(".tabs ul li").first().addClass("active");
$('.tabs').next().css("display", "block");
}
}
tabs();
$(".tabs ul li").click(function(e) {
$(".tabs ul li").removeAttr("class");
$(this).addClass("active");
$(".content").hide();
var contentClass = "." + $(this).find("a").attr("href").substr(1);
$(contentClass).fadeIn();
window.location.hash = $(this).find("a").attr("href");
e.preventDefault();
return false;
});
URL without any hash.
http://output.jsbin.com/tojeja
URL with hashtag that does not jumping to anchor.
http://output.jsbin.com/tojeja#content1
I'm not sure if this produces the desired outcome, give it a shot:
$('<a href="#">').text('unlink').click(function(e) {
e.preventDefault();
var st = parseInt($(window).scrollTop())
window.location.hash = '';
$('html,body').css( { scrollTop: st });
});
Basically save the scroll offset and restore it after assigning the empty hash.
This is an old post but I wanted to share my solution All the links in my project that being handled by JS are having href="#_js" attribute (or whatever name you want to use for that purposes only), and on page initialization I do:
$('body').on('click.a[href="#_js"]', function() {
return false;
});
That'll do the trick