how to catch a state change event ONCE with history.js?

Alexander Morland picture Alexander Morland · Oct 13, 2011 · Viewed 11.8k times · Source

I have an example code below where if you click the links, then use back and forward, each state change will cause more and more hits on the 'statechange' event. Instead of the one that I expect.

Links:

Code:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>History start</title>
</head>
<body>
    <h1>Headline</h1>
    <hr>
    <div id="menu">
        <ul>
            <li>
                <a href="page-1">Page 1</a>
                <div style="display:none;">
                    <h2>Page 1</h2>
                    <p>Content 1</p>
                </div>
            </li>
            <li>
                <a href="page-2">Page 2</a>
                <div style="display:none;">
                    <h2>Page 2</h2>
                    <p>Content 2</p>
                </div>
            </li>
        </ul>
    </div>
    <hr>
    <div id="content">
        <h2>Start page</h2>
        <p>Paragraf</p>
    </div>
    <script src="external/jquery-1.6.2.min.js"></script>
    <script>if ( typeof window.JSON === 'undefined' ) { console.log("Loaded json2"); document.write('<script src="external/json2.js"><\/script>'); }</script>
    <script src="external/history.adapter.jquery.js"></script>
    <script src="external/history.js"></script>
    <script>
    $(document).ready(function() {
        History.enabled = true;

        $('a').each(function() {
            $(this).click(function(e) {
                e.preventDefault();
                var $link = $(e.target),
                    state = {'href': $link.attr('href'), 'title': $link.html()},
                    $div = $link.siblings('div'),
                    content = $div.html();

                $('#content').html(content);

                History.pushState(state, state.title, state.href);

                return false;
            });
        });

        History.Adapter.bind(window, 'statechange', function() {
            var State = History.getState();
            // remove double hit on event
            console.log(State);

        });

    });
    </script>
</body>
</html>

Answer

Jared picture Jared · Nov 30, 2011

It's because you're calling the pushState function when you load the page, which also causes a statechange. I was in a similar situation and used a but a boolean before my pushStates so I knew I was doing a pushState. It looks like this...

historyBool = true;
History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate

var State = History.getState(); // Note: We are using History.getState() instead of event.state

    //don't run our function when we do a pushState
    if(historyBool){
        historyBool = false;
        tempFunction = new Function(State.data.ajaxRunFunction);
        tempFunction();
    }
    historyBool = true;
});

historyBool = false;
historySet = {ajaxRunFunction: "upc('" + pageID + "','')"};
History.pushState(historySet,"","");