On a one page layout with fixed top menu and anchor navigation I have a "scrollspy" in place that changes the fragment identifier on scroll, gives the menu link an active class depending on scroll position and animates the scrolling to the anchor with Velocity.js.
Unfortunately what it also does, when clicking the browser back button it takes me through all the steps of the scrolled way, meaning I load the site and scroll down and up a tiny bit and then hit the back button frequently the browser will also scroll down and up but won't go to either the last visited id or back in browser history actually.
// jQuery on DOM ready
// In-Page Scroll Animation with VelocityJS
// ------------------------------------------------ //
// https://john-dugan.com/fixed-headers-with-hash-links/
$('.menu-a').on('click', function(e) {
var hash = this.hash,
$hash = $(hash)
addHash = function() {
window.location.hash = hash;
};
$hash.velocity("scroll", { duration: 700, easing: [ .4, .21, .35, 1 ], complete: addHash });
e.preventDefault();
});
// ScrollSpy for Menu items and Fragment Identifier
// ------------------------------------------------ //
// https://jsfiddle.net/mekwall/up4nu/
$menuLink = $('.menu-a')
var lastId,
// Anchors corresponding to menu items
scrollItems = $menuLink.map(function(){
var item = $($(this).attr("href"));
if (item.length) { return item; }
});
$(window).scroll(function(){
// Get container scroll position
var fromTop = $(this).scrollTop()+ 30; // or the value for the #navigation height
// Get id of current scroll item
var cur = scrollItems.map(function(){
if ($(this).offset().top < fromTop)
return this;
});
// Get the id of the current element
cur = cur[cur.length-1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
// Set/remove active class
$menuLink
.parent().removeClass("active")
.end().filter("[href='#"+id+"']").parent().addClass("active");
}
// If supported by the browser we can also update the URL
// http://codepen.io/grayghostvisuals/pen/EtdwL
if (window.history && window.history.pushState) {
history.pushState("", document.title,'#'+id);
}
});
With the above code the following works fine:
The hash or fragment identifier updates fine when clicked on the menu link using VelocityJS for the scrolling animation.
The active class is given to the corresponding menu link on scrolling.
The fragment identifier also updates fine when scrolling instead of clicking the menu link.
Question
Part 1: When you scroll a tiny bit on the fiddle and then hit the back button you will see that the scrollbar "travels" the exact same way, remembering the scrolling that was done.
I need the back button to work like it normally does. a) Either go back in browser history and return to the page/site you were on and b) when having clicked an anchor link (i) and then anchor link (ii) and then the back button the page should go back to anchor link (i).
Part 2: Since history.pushState
is not supported in IE8 I am looking for a way to use window.location.hash = $(this).attr('id');
instead. No matter what I have tried towards the end of the code I simply cannot get window.location.hash = $(this).attr('id');
to work. I don't really want to use HistoryJS or something for this but am interested to learn this and write it myself.
Apart from the back button broken behaviour all the other behaviour that I want is already there, now I just need to fix the back button behaviour.
edit I think I might have found a solution here, will test and then reply in detail if I get this to work.
Related:
smooth scrolling and get back button with popState on Firefox - need to click twice
jQuery in page back button scrolling
Modifying document.location.hash without page scrolling