Search code examples
javascriptpushstate

weird issue with pushState/popstate - initial page seems to have been "pushed" twice


I'm having a weird issue with pushState/popstate where it seems my initial page is saved twice.

It's a bit hard to explain without an example.

something like this:

  1. current page is www.bing.com
  2. copy/paste my URL into URL bar and page loads
  3. click on a link on the page (this link fires an AJAX request which then manipulates the DOM to display the data retrieved.)
  4. press back button which brings me to the same page as in step2
  5. press back button again but I'm still on the the same page as step2/4
  6. press back button again and this bring me back to www.bing.com

As you can see, I need to press the back button twice to get me back to www.bing.com when it should have only needed 1.

a short explanation of my page (code is at the bottom of the page):

  1. when the page loads, initial list for the dropdown selection is retrieved via AJAX and populates the select tag.

  2. user has option to click on 3 links which determine the contents of the dropdown selection. Example: If I click on Option B link, this fires the same AJAX from step1 but only retrieves data suitable for Option B.

  3. The user makes a selection from the dropdown and presses search. This triggers another AJAX function which retrieves the relevant data and displays the formatted information inside the mysearchresults div.

  4. I tried playing around with placement (e.g. before or after AJAX call) of pushState and the placement now seems the one that give me the least problem. Although I do encounter the issue I mentioned above.

Here's my code. I had to strip out a lot of code/functions to make it short and readable but please be assured the AJAX calls/data display are working.

<div id="content">
    <p>
        <a class="coursetype" href="#" data-type="B">Option B</a>
        | <a class="coursetype" href="#" data-type="H">Option H</a>
        | <a class="coursetype" href="#" data-type="BG">Option BG</a>
    </p>

    <form id="myform">
        <label class="formlabel" for="course">Select your course</label>
        <br /><select id="course" name="course"></select>
        <button id="searchbutton" type="button">Search Me</button>
    </form>

    <div id="mysearchresults"></div>
</div>

$(document).ready(function() {
    var onClickCourseTypeHandler = function(event) {
        event.preventDefault();

        getCourses({ type:$(event.target).data("type") });

        window.history.pushState({ html:$("#content").html(), coursecode:$("#coursecode").val() }, "", main?type="+pagevars.type);
    }

    var onClicksearchbuttonHandler = function(event) {
        if ($("#coursecode").val().length > 0) {
            searchDB({ course:$("#course").val() });

            window.history.pushState({ html:$("#content").html(), coursecode:$("#coursecode").val() }, "", "/main?&course="+$("#course").val());
        }
    };

    $(document).on("click", ".coursetype", onClickCourseTypeHandler);

    $(document).on("click", "#searchbutton", onClicksearchbuttonHandler);

    try {
        window.addEventListener("popstate", function(event) {
            if (event.state) {
                $("#content").html(event.state.html);

                if (event.state.coursecode.length > 0) {
                    if ($("#course option[value='" + event.state.course + "']").length > 0) {
                        $("#course").val(event.state.course);
                    } else {
                        $("#course option:first-child").attr("selected", "selected");
                    }
                }
            }
        });
    } catch(exception) {
    }

    onLoad();

    function onLoad() {
        getCourses({ type:"" });

        window.history.pushState({ html:$("#content").html(), course:dbvars.course }, "", "/main");
    }

    function searchDB(parameters) {
        $.ajax({
            url: baseurl+"/searchDB"
            , cache: false
            , dataType: "json"
            , data: { format:"json", course:parameters.course }
            , success: function(data, status) {
                parameters.data = data;
                displaySearchResults(parameters);
            }
        });
    }

    function getCourses(parameters) {
        if (typeof(parameters.cacheflag) === "undefined") { parameters.cacheflag = false; };

        $.ajax({
            url: baseurl+"/getCourses"
            , cache: parameters.cacheflag
            , dataType: "json"
            , data: { format:"json", coursetype:parameters.type }
            , success: function(data, status) {
                parameters.data = data;
                populateCourses(parameters);
            }
        });
    }
});

Solution

  • When you load your page, it gets added to the History, so when you do history.pushState it's added a second time. Try replacing history.pushState with history.replaceState in the onload function.