lunjius
lunjius

Reputation: 418

Prevent Ajax website from jumping back to top after back-button-press

I am currently working on a website with ajax support. Navigating through website and the browser's history works great, but there is one problem I cannot solve.

When the user presses the back button, the last page appears again. But although I set the vertical scroll position to the previous one via popstate event, it jumps back to top again...

function loadContent(nextContent, nextUrl, newPage = true) {
    var currUrl = window.location.pathname;
        currUrl = currUrl.slice(7,currUrl.length);
    var scrollY = window.scrollY;
    var prevContent = document.getElementById("page").innerHTML;

    document.getElementById("page").innerHTML = nextContent;

    if (newPage) {

        // overwrite current history entry
            history.replaceState({ content: prevContent, url: currUrl, scrollY: scrollY }, null, currUrl);

        initPage();
        window.scrollTo(0,0);

        // write new entry
            history.pushState({ content: nextContent, url: nextUrl, scrollY: 0 }, null, nextUrl);

    } else {
        initPage();
        // scroll to previous scroll position
        window.scrollTo(0,history.state.scrollY);
    }
}

window.onpopstate = function(e) {
    loadContent(e.state.content, e.state.url, false);
    // page scrollY will be set in load, after page content was added
}

I know that the code works so far because earlier I've put an alert after window.scrollTo() and during the freeze I saw, that the page is on the correct position. But after continuing it jumped to the top. Is there maybe another (default) event, that scrolls to the top in the background?

Thanks for help

Upvotes: 0

Views: 350

Answers (1)

lunjius
lunjius

Reputation: 418

I fixed the problem now by changing the onpopstate function to the following:

window.onpopstate = function(e) {
    loadContent(e.state.content, e.state.url, false);

    // as previous window.scrollTo() have no effect, do it within a few millisecs again
    setTimeout(function() {
        window.scrollTo(0,history.state.scrollY);
    }, 5);
}

Not really beautiful, but it works. If someone knows a clean fix or the reason why this effect happens, please share your knowledge!

Upvotes: 1

Related Questions