The solution to back / forward buttons for Ajax based applications
A major problem in Javascript/Ajax based applications, is unable to use the browser buttons (back, forward).
Here is a solution to this problem, based on Prototype, of course!

The interface proposed here allows you to easily manage parameters in the hash of the url. These settings work the same way as parameters GET an HTTP request.

Here, the parameter name will be the 'namespace', and the value will be the 'state'. You can have as many namespaces as you wish.
Then History.Registry allows you to record a callback function for a 'namespace'. When the parameter change value, the callback function will be called.

This will put in place very simply the management of browsing history, for Ajax, but more generally for all your JavaScript applications.
History
History is based on Hash of Prototype. It helps define dynamically variables in the hash of the url.
Set parameters on hash :
// location.href == '/index.html'

History.set('foo', 'bar');

// location.href == '/index.html#foo=bar'

History.set('page', 'home');

// location.href == '/index.html#foo=bar&page=home'
Get parameters on hash :
History.get('foo');  // == 'bar'
History.get('page'); // == 'home'
Unset parameters on hash :
History.unset('foo');

// location.href == '/index.html#page=home'

History.unset('page');

// location.href == '/index.html#'
Technical Specifications for Internet Explorer
Again, Internet Explorer (6 and 7) are problematic
Internet Explorer 6 and 7
Indeed, versions 6 and 7 manages not browsing history in the same way as its competitors.
Test it, if we change the hash of the url, this change will not be taken by the history manager of Internet Explorer.
That is why we have integrated a system based on a hidden iframe (exclusively for versions 6 and 7 of IE).
Meanwhile Internet Explorer 8.0...
Note that for IE 8, the history management is now optimal, the hidden iframe is not used.
On Internet Explorer 8 (soon), an event has been added: onhashchange (this event is provided by the HTML 5)
This event is very convenient because it avoids the observation of hash without PeriodicalExecuter.
When IE 8 will be officially released, this feature may be implemented only for IE 8 (other browsers will operate as before).
History.Observer
History.Observer can start or stop the dispatcher with PeriodicalExecuter of Prototype.
The dispatcher is a function that scans the current hash and dispatch each parameter to its user-defined function in History.Registry.

For now, is the most practical solution to put in place so that the system works on most web browser. When events like onhashchange will be implemented on most modern browsers, this solution will be implemented.
Start observer
History.Observer.start();
Stop observer
History.Observer.stop();
Set interval delay
By default, the period of observation is set to 0.2 sec. (200ms). This is the minimum recommended.
However, you can set a longer period, note that if the delay is long, the navigation with back/forward buttons will be long too.
// Set observe delay to 0.5 sec. (500 ms)
History.Observer.delay = 0.5;
History.Registry
History.Registry ability to store functions to call if a specific parameter is found in the hash of the URL.
This helps to simulate back / forward actions.
Simple example
When set new value of parameter 'page' , the handler is called and value of 'page' is logged in console
// Start observe
History.Observer.start();

// Set handler for 'page' parameter
History.Registry.set('page', function(value) {
    console.log(value);
});

// Set value for page
History.set('page', 'home');

Ajax.History provided features
Three parameters are provided by Ajax.History allowing you to configure the browsing history manager.
A callback has also been introduced: onStateChange(string state).
This callback is launched when the state of the browsing history points to the request.
This allows for example to change the title of the page according to the state (see example below).
Name Default value Required Description
history.id null Yes Unique identifier used in the url. This parameter is optionnal on Ajax.History.Updater.
history.state null No The state of the history.id. This parameter is optional. If it is set to false, a system of automatic statements will be used.
history.cache false No If enabled (true), Ajax Requests will be simulated via Ajax.Cache when the user will use the buttons back / forward of browser.
history.onStateChange null No Define a callback function fired when state change.
Ajax.History.Request
Ajax.History.Request used exactly as Ajax.Request of Prototype.
For an interactive example, we create a simple function:
function ajaxHistoryRequest(url, myState) 
{
    new Ajax.History.Request(url, {
        history : {
            id    : 'example',
            state : myState,
            cache : true,
            onStateChange: function(state) {
                // change title
                History.setTitle(History.getTitle() + ' - Page Ajax #' + state);
            }
        },
        onSuccess: function(transport) {
            $('box-example').update(transport.responseText);
            // some stuff
        }
    });
}
Now click on 'Execute' to perform the function
When you click 'Execute', watch the URL and title of the page on your browser.
After clicking on the three buttons 'Execute', try to back/forward** on your browser. Magic! :)
ajaxHistoryRequest('history/request1', 'first-test');
ajaxHistoryRequest('history/request2', 'second-test');
ajaxHistoryRequest('history/request3', 'third-test');
** The cache is enabled, if you use a module as FireBug on Firefox, you can see that the use of buttons back/forward of your browser does not reload the Ajax.Request.
Ajax.History.Updater
Ajax.History.Updater used exactly as Ajax.History.Request :
Automatic historyId :
Here, the historyId is not declared, the 'containerName' is used automatically.
new Ajax.History.Updater('containerName', 'my/url/to/load.html', {
    history : {
        cache : true
    }
});

// location.href == '...#containerName={state}'
Disable historyCache :
The cache is disabled, so, when user perform back/forward of browser, the Ajax Request will be loaded whenever.
new Ajax.History.Updater('containerName', 'my/url/to/load.html', {
    history : {
        id    : 'my-own-identifier',
        cache : false
    }
});

// location.href == '...#my-own-identifier={state}'
Ajax.Cache
How does the cache?
Ajax.Cache can "simulate" an Ajax Request from an Ajax Request made beforehand. It takes only one argument: the object Ajax.Request / Updater create first.
In fact, Ajax.Cache is based on a modified prototype Ajax.Request API. Yes, to simulate the request, I remove the mechanism (real) sending the HTTP request.
Perform simulation manually :
Ajax.Cache is already implemented in Ajax.History.* classes. However, you can use it manually :
// the request is executed firstly
var request = new Ajax.Request('my/url/to/load.html', {
    method: 'POST',
    ...
});

// reproduced the Ajax.Request without HTTP request
new Ajax.Cache(request);

Copyright 2008 Simon Martins - License