https://github.com/browserstate/history.js
Я использую примерно так:
$(window).bind('statechange', function () {
var State = History.getState();
var url = State.url;
var data = State.data;
if (ajaxRequest) {
ajaxRequest.abort();
} else {
$resultContainer.html('<div class="ajax-loader" style="position:relative;"><img src="http://i.imgur.com/6RMhx.gif" /></div>');
}
ajaxRequest = $.ajax({
url: url,
data: data,
dataType: 'json',
success: function (data, textStatus, jqXHR) {
$resultContainer.html(data.content);
if (data.form) {
$filterForm.html(data.form);
filterFormInitCallback();
}
ajaxRequest = null;
},
error: function (jqXHR, textStatus, errorThrown) {
if ('abort' != textStatus) {
document.location.href = url;
}
return false;
}
});
});
$filterForm.submit(function () {
var query = $(this).formSerialize();
// decodeURIComponent т.к. formSerialize выдает закодированный урл, а histoty.js пытается закодировать его еще раз
History.pushState(null, document.title, '?' + window.decodeURIComponent(query));
return false;
});