Is this a proper way to use History.js?
Asked Answered
F

1

10

I was able to put together a simplified complete History.js example using three links to load fragments of content from a full page without updating the page and while updating the browser history.

Here are the relevent code snippets - a complete working example is here http://jsfiddle.net/PT7qx/show

<a href="/page-header">Page Header</a>
<a href="/login-form">Login Form</a>
<a href="/nothing">Nothing</a>

<script>
var History = window.History;
if (!History.enabled) {
    return false;
}

History.Adapter.bind(window, 'statechange', function() {
    var State = History.getState();
    History.log(State.data, State.title, State.url);

    if (State.title == 'Page Header') {
        $('#content').load('/user/login/ .pageHeader > *');
    }

    if (State.title == 'Login Form') {
        $('#content').load('/user/login/ #common-form > *');
    }

    if (State.title == 'Nothing') {
        $('#content').empty()
    }
});

$('body').on('click', 'a', function(e) {

    var urlPath = $(this).attr('href');
    var Title = $(this).text();
    History.pushState(null, Title, urlPath);

    // prevents default click action of <a ...>
    return false;
});
<\script>

I would like to know if this is the correct usage. The previous version had an ability to bind to an event using the # urls. I have not seen any examples for binding events to urls with this latest version so I used the .on() click event to call History and sorted out what link was clicked in there.

I am not sure if this is the best way to accomplish this for this example.

Fugate answered 7/11, 2012 at 21:47 Comment(0)
F
21

After working on this some more, I have come up with a simple, but complete example for how to use the latest History.js. Here is working jsfiddle example that does Ajax loads of HTML fragments hosted on Github

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Simple History.js Ajax example by dansalmo</title>

    <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.js"></script>
    <script type="text/javascript" src="http://balupton.github.com/history.js/scripts/bundled/html4+html5/jquery.history.js"></script>

    <style type='text/css'>
      .hidden {
        display: none;
        visibility: hidden;
      }
    </style>
  </head>
  <body>
    <a href="/home">Home</a>
    <a href="/about">About</a>
    <a href="/contact">Contact</a>
    <a href="/other">Other</a>

    <p>The whole page will not re-load when the content below is updated, yet the URL is clean and the back button works!<p><br />
    <div id="content">
      <div id="home">Home Page content</div>
    </div>
    <br />
    <p>The content div will be updated with a selected div fragment from an HTML file hosted on github, however the broswer will see each content update request as a part of the page history so that the back button can be used.</p>
    <br  />
    <p>Adding more menu items is as simple as adding the new links and their corresponding html fragments.<p>
    <div id="hidden_content" class="hidden"></div>
  </body>
    <script type='text/javascript'>//<![CDATA[ 
  $(function(){
  var History = window.History;
  if (History.enabled) {
      State = History.getState();
      // set initial state to first page that was loaded
      History.pushState({urlPath: window.location.pathname}, $("title").text(), State.urlPath);
  } else {
      return false;
  }

  var loadAjaxContent = function(target, urlBase, selector) {
      $(target).load(urlBase + ' ' + selector);
  };

  var updateContent = function(State) {
      var selector = '#' + State.data.urlPath.substring(1);
    if ($(selector).length) { //content is already in #hidden_content
        $('#content').children().appendTo('#hidden_content');
        $(selector).appendTo('#content');
    } else { 
        $('#content').children().clone().appendTo('#hidden_content');
        loadAjaxContent('#content', State.url, selector);
    }
  };

  // Content update and back/forward button handler
  History.Adapter.bind(window, 'statechange', function() {
      updateContent(History.getState());
  });

  // navigation link handler
  $('body').on('click', 'a', function(e) {
      var urlPath = $(this).attr('href');
      var title = $(this).text();
      History.pushState({urlPath: urlPath}, title, urlPath);
      return false; // prevents default click action of <a ...>
  });
  });//]]>  

  </script>
</html>
Fugate answered 9/11, 2012 at 19:12 Comment(6)
I'm a bit late to the party, but it's worth noting that History.pushState({urlPath: window.location.pathname()}, $("title").text(), State.urlPath); will throw an error, as window.location.pathname() isn't a function. Just remove the parentheses and it works like a charm.Latrishalatry
Thanks for catching that. Not sure how I missed it since I had thought I was pasting it from a working version.Fugate
@dansalmo, If I implement an example like the one you showed above (https://mcmap.net/q/589797/-is-this-a-proper-way-to-use-history-js) then where do I put the additional content relative to the index.html file? Do I put it in a response.html that is in the same folder as index.html?Westminster
Yes. At least using the server framework that I am using. I use Google App Engine with Python 2.7.Fugate
am i have to send entire page on target link or just some part of page of target link?Emissivity
How would I get this working on a simple slide down like this? Is it possible to save the state where the div is slid down so that if I enter the url into the browser, it loads it with the div slid down?Importunate

© 2022 - 2024 — McMap. All rights reserved.