Search code examples
javascripthtmlback-buttonhtml5-history

pushState Executing When Not Supposed To


I am using the HTML history API to manipulate the browser history stack to control navigation using JavaScript on my site. The function I have set up to change pages is working fine, but weirdly, when I added pushState to each individual page change, the pushState fires automatically, so that the last page change in the function is always the final one executed. This means the state being pushed is always the last page change statement.

The JavaScript:

// Change Page Function

function ChangeContent (page) {

var pages={"homepage":{title: "homepage"},"servicespage":{title: "servicespage"},"estimatespage":{title: "estimatespage"}};

HideNav();

//Show home page
for(var homepage in pages) {

    if(page!==homepage) {

        document.getElementById(homepage).style.display='none';
    }

    else {

        document.getElementById(homepage).style.display='block';
        history.pushState("homepage", "Home", "home" );
        window.scrollTo(0,0);
    }
}

//Show services page
for(var servicespage in pages) {

    if(page!==servicespage) {

        document.getElementById(servicespage).style.display='none';
    }

    else {

        document.getElementById(servicespage).style.display='block';
        history.pushState( "servicespage", "Our Services", "services");
        window.scrollTo(0,0);
    }
}

//Show estimates page
for(var estimatespage in pages) {

    if(page!==estimatespage) {

        document.getElementById(estimatespage).style.display='none';
    }

    else {

        document.getElementById(estimatespage).style.display='block';
        history.pushState( "estimatespage", "Get An Estimate", "estimates");
        window.scrollTo(0,0);
    }
}
}

When you run this code, instead of each individual page pushing it's state when that page is clicked, the state getting pushed is always the estimates page state. I've tried using else if statements instead, and I've tried embedding each for statement into self executing functions in the hope that it might solve a scope issue of some kind, but I've had no luck.

This is my onPopstate function:

// History State Change Display
window.onpopstate = function (event) {

var state = event.state;

console.log(state);

// Change History State Display To Home Page
if (state === "homepage") {

    document.getElementById("homepage").style.display = 'block';
} else {

    document.getElementById("homepage").style.display = 'none';
}

// Change History State Display To Services Page
if (state === "servicespage") {

    document.getElementById("servicespage").style.display = 'block';
} else {

    document.getElementById("servicespage").style.display = 'none';
}

// Change History State Display To Estimates Page
if (state === "estimatespage") {

    document.getElementById("estimatespage").style.display = 'block';
} else {

    document.getElementById("estimatespage").style.display = 'none';
}
};

For some reason each new page I click on has the URL extensions /estimatespage and then when I click the back button, it just cycles through the pages in reverse order in which they were written in the page change function, and properly updates the URL.

I'm not totally sure what the issue here is, but I think I'm pushing the state of all the pages automatically, which is weird, since the rest of the code is only executing when the proper page is selected.

Any help would be appreciated, as I think this is probably more obvious than I'm making it out to be.

HTML

<div id="nav">
     <div class="headerlist" onclick="ChangeContent('homepage');">Home</div>
     <div class="headerlist" onclick="ChangeContent('servicespage');">Services</div>
     <div class="headerlist" onclick="ChangeContent('estimatespage');">Estimates</div>
</div>

<div id=homepage></div>
<div id=servicespage></div>
<div id=estimatespage></div>

Solution

  • You have three for loops in ChangeContent(). All three loops are testing for exactly the same condition -- merely with a renamed variable.

    Keeping the style vaguely the same, you might try this instead, note that this single loop is to replace all three of those loops in ChangeContent():

            for ( var p in pages ) {
                if  ( page !== p ) {
                    document.getElementById( p ).style.display = 'none';
                }
                else {
                    document.getElementById( p ).style.display = 'block';
                    if ( p === "homepage" )
                        history.pushState( "homepage", "Home", "home" );
                    else if ( p === "servicespage" )
                        history.pushState( "servicespage", "Our Services", "services");
                    else if ( p === "estimatespage" )
                        history.pushState( "estimatespage", "Get An Estimate", "estimates");                    
                    window.scrollTo( 0, 0 );
                }
            }