Cross-browser jquery ajax history with window.history.pushState and fallback
// Assuming the path is retreived and stored in a variable 'path'if (typeof(window.history.pushState) == 'function') { window.history.pushState(null, path, path);} else { window.location.hash = '#!' + path;}
Something i've been using with fallback hash URL's:
History = History || {};History.pathname = null;History.previousHash = null;History.hashCheckInterval = -1;History.stack = [];History.initialize = function () { if (History.supportsHistoryPushState()) { History.pathname = document.location.pathname; $(window).bind("popstate", History.onHistoryChanged); } else { History.hashCheckInterval = setInterval(History.onCheckHash, 200); }};History.supportsHistoryPushState = function () { return ("pushState" in window.history) && window.history.pushState !== null;};History.onCheckHash = function () { if (document.location.hash !== History.previousHash) { History.navigateToPath(document.location.hash.slice(1)); History.previousHash = document.location.hash; }};History.pushState = function (url) { if (History.supportsHistoryPushState()) { window.history.pushState("", "", url); } else { History.previousHash = url; document.location.hash = url; } History.stack.push(url);};History.onHistoryChanged = function (event) { if (History.supportsHistoryPushState()) { if(History.pathname != document.location.pathname){ History.pathname = null; History.navigateToPath(document.location.pathname); } }};History.navigateToPath = function(pathname) { History.pushState(pathname); // DO SOME HANDLING OF YOUR PATH HERE};
You could bind your click events to this with:
$(function(){ $("a").click(function(){ var href = $(this).attr('href'); History.navigateToPath( href ) return false; });});
If you need some more explanation on this example i'll be glad to hear it.
EDIT
Please see my other answer.
It has been a while since my original answer and I would now suggest using Backbone.
An implementation could be:
// First setup a router which will be the responder for URL changes:var AppRouter = Backbone.Router.extend({ routes: { "*path": "load_content" }, load_content: function(path){ $('#content').load('/' + path); }});var appRouter = new AppRouter;// Then initialize Backbone's historyBackbone.history.start({pushState: true});
Excerpt from the documentation:
To indicate that you'd like to use HTML5
pushState
support in your application, useBackbone.history.start({pushState: true})
. If you'd like to usepushState
, but have browsers that don't support it natively use full page refreshes instead, you can add{hashChange: false}
to the options.
And now every time Backbone.history.navigate
is called, the AppRouter
will perform an AJAX load of the path into the #content
div.
To handle all links with AJAX you could use the following:
$("a").on('click', function(event){ event.preventDefault(); Backbone.history.navigate( event.currentTarget.pathname, {trigger: true} )});
Take note of the {trigger: true}
which causes the handler in the router to be called (otherwise only from url changes).