History.js getState() at pageload
Asked Answered
A

2

7

I'm a little confused about how History.js works at page-load. I've done a few experiments but the results seem indeterministic.

My website is a search engine and the query is stored in the URL parameters: ?Query=cats. The site is written purely in javascript. History.js works great when I do a new search, the new query is updated, and the state is pushed.

My problem is how to create an initial state if the user manually enters in a URL including a Query parameter. Every way I try to do this ends up resulting in running the search query twice in some case. The two use-cases that seem to conflict are:

  1. User manually enters URL (mydomain.com?Query=cats) into address bar and hits enter.
  2. User navigates to an external page, and then clicks the back button

In both cases, the javascript loads, and therefore looks to the URL parameters to generate an initial state.

However, in the second case, History.js will trigger the statechange event as well.

Necessary code:

    History.Adapter.bind(window,'statechange',function() { // Note: We are using statechange instead of popstate
        var s = History.getState();
        if(s.data["Query"]){
          executeQuery(s.data);
        }
    });

and in $(document).ready I have

  // Get history from URL
  s = getQueryObjectFromUrl(location.href);
  if(s["Query"]){
      History.pushState(s,'',$.param(s))
  }

Is there a better way to handle creating an initial state from URL parameters?

Adversaria answered 29/7, 2013 at 18:0 Comment(2)
Why don't you give user results from e.g. PHP when he goes to /?Query=dasd directly?Unassuming
What about for client side applications? realpage.html/dynamicAppState gets picked up by the server as a directory that doesnt exist forcing you to to rewrite or htaccess and the correct page never gets loaded. You shouldnt need to write any server code to get this to work... its a client side utility. When # is used, the index.html gets loaded and the data after the # can be easily parsed. What do you do now?Topmast
H
1

As I had a similar problem to to yours, what i did was to define the function bound to a statechange as a named function, and then all I had it running when the page load as well.

It worked better than trying to parse the URI or anything else, hope it helps.

Highams answered 26/11, 2013 at 18:10 Comment(0)
L
1

This is the way I chose to do it (based on Fabiano's response) to store the initial state parameters

var renderHistory = function () {
    var State = History.getState(), data = State.data;
    if (data.rendered) {
        //Your render page methods using data.renderData
    } else {
        History.replaceState({ rendered: true, renderData: yourInitData}, "Title You Want", null);
    }
};
History.Adapter.bind(window, 'statechange', renderHistory);
History.Adapter.onDomLoad(renderHistory);

Of course if you are using a different on DOM load like jquery's you can just place renderHistory(); inside of it, but this way doesn't require any additional libraries. It causes a state change only once and it replaces the empty initial state with one containing data. In this way if you use ajax to get the initData inside the else, and it will not need to get it the next time the person returns to the page, and you can always set rendered to false to go back to initial page state / refresh content.

Labarbera answered 19/7, 2014 at 6:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.