All-in-one location/hashchange history management library

user123444555621 picture user123444555621 · Jul 11, 2012 · Viewed 15.1k times · Source

First of all, I know there's libraries that provide polyfills for location.pushState/popState (History.js, Hash.js, jQuery hashchange), so please don't just link to those.

I need a more powerful library to achieve the following in a RIA:

  1. User clicks a link
  2. library is notified and loads context via Ajax (no complete reload!)
  3. All <a> elements are leveraged with a click handler that
    • prevents page reloads in 2. (preventDefault) and
    • calls location.pushState instead / sets location.hash for older browsers
  4. loaded content is inserted in page and replaces current content
  5. Continue with 1.

Also, previously loaded content should be restored as the user navigates back.

As an example, klick through Google+ in Internet Explorer <10 and any other browser.

Is there anything that comes even close? I need support for IE8, FF10, Safari 5 and Chrome 18. Also, it should have a permissive license like MIT or Apache.

Answer

Geert-Jan picture Geert-Jan · Jul 13, 2012

I believe Sammy.js ( http://sammyjs.org) (MIT-licenced) has the best focus on what you want to do, with its 2 main pillars being:

  1. Routes
  2. Events

I could quote from the docs but it's pretty straightforward:

  • setup clientside routes that relate to stuff to be done, e.g: update the view through ajax

  • link events to call routes, e.g: call the route above when I click an link. (You would have to make sure e.preventDefault is called in the defined event I believe, since this is an app decision really, so that can't be abstracted away by any library that you're going to use imho)

Some relevant docs

Example for a route: (from http://sammyjs.org/docs/tutorials/json_store_1)

 this.get('#/', function(context) {
    $.ajax({
      url: 'data/items.json',
      dataType: 'json',
      success: function(items) {
        $.each(items, function(i, item) {
          context.log(item.title, '-', item.artist);
        });
      }
    });
  });

Or something like

 this.get('#/', function(context) {
     context.app.swap(''); ///the 'swap' here indicates a cleaning of the view
                              //before partials are loaded, effectively rerendering the entire screen. NOt doing the swap enables you to do infinite-scrolling / appending style, etc. 
     // ...
   });

Of course other clientside MVC-frameworks could be an option too, which take away even more plumbing, but might be overkill in this situation.

a pretty good (and still fairly recent) comparison:

http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/ ( I use Spine.js myself ) .

Lastly, I thought it might be useful to include an answer I've written a while ago that goes into detail to the whole best-practice (as I see it) in client-side refreshes, etc. Perhaps you find it useful:

Accessibility and all these JavaScript frameworks