Hi Ajaxians,
In the last post we showed off a tiny tool that should make life easier writing Ajax for Rails apps using jQuery. The ideas was to separate (like everyone) the code from the design (which could be incrementally built with as little fuss as possible).
Of course, the back button of the browser reminds us all of the bad days on ugly browser refreshing. To Ajaxians it was a nightmare to support. Of course tons of libraries handle it for you so we thought we'd pitch in.
While there's a perfectly simply line to set a hash on the page location:
There is no JavaScript event to be handled showing the change of a hash. One has to frequently poll to detect any change. Thankfully, the "Cowboy" Ben Alman comes to the rescue with a small file that does just that: It can be found at http://benalman.com/projects/jquery-hashchange-plugin/.
Now lets put that into our little tool box. We'll create an array to be used as a hash map, literally. It should save all our hash values and associate them with JavaScript objects. That way we can save them and reuse them when we have to.
To use our history of hashes we have to add an item to it whenever we Ajaxify our links.
The function that adds the hash to the browser's history this has to be careful not to fire unnecessary calls. We need to set our hash values in code BUT ONLY trigger ajax calls when the user hits the next or back browser buttons.
The tricky thing to grasp is that the history map actually saves the click events that were triggered. This allows complex events to run; the whole stage can change. Compare this to simpler implementations that save a "url" to navigate to. I wince at the comparison.
To make any link enforce its history we provide a custom attribute on that link. We simple add (history="my-hash") to the tag and voila, it adds itself to the history and you can backtrack to it.
Finally. A solution that keeps record of any notable changes in the application and offers a history based on events.
In the last post we showed off a tiny tool that should make life easier writing Ajax for Rails apps using jQuery. The ideas was to separate (like everyone) the code from the design (which could be incrementally built with as little fuss as possible).
Of course, the back button of the browser reminds us all of the bad days on ugly browser refreshing. To Ajaxians it was a nightmare to support. Of course tons of libraries handle it for you so we thought we'd pitch in.
While there's a perfectly simply line to set a hash on the page location:
window.location.hash = 'My-Hash';
There is no JavaScript event to be handled showing the change of a hash. One has to frequently poll to detect any change. Thankfully, the "Cowboy" Ben Alman comes to the rescue with a small file that does just that: It can be found at http://benalman.com/projects/jquery-hashchange-plugin/.
Now lets put that into our little tool box. We'll create an array to be used as a hash map, literally. It should save all our hash values and associate them with JavaScript objects. That way we can save them and reuse them when we have to.
function HistoryMap()
{
this.length = 0;
this.items = new Array();
for (var i = 0; i < arguments.length; i += 2) {
if (typeof(arguments[i + 1]) != 'undefined') {
this.items[arguments[i]] = arguments[i + 1];
this.length++;
}
}
this.getItem = function(in_key) {
return this.items[in_key];
}
this.setItem = function(in_key, in_value) {
var tmp_previous;
if (typeof(in_value) != 'undefined') {
if (typeof(this.items[in_key]) == 'undefined') {
this.length++;
}
else {
tmp_previous = this.items[in_key];
}
this.items[in_key] = in_value;
}
return tmp_previous;
}
this.hasItem = function(in_key) {
return typeof(this.items[in_key]) != 'undefined';
}
}
var historyMap = new HistoryMap()
To use our history of hashes we have to add an item to it whenever we Ajaxify our links.
// In the ajaxify function, we had the following:
$('a[into]').unbind('click' );
$('a[into]').bind('click', ajaxClick);
// We have to add this immediately after:
if (HistoryMap) $('a[history]').bind('click', hashHistory);
The function that adds the hash to the browser's history this has to be careful not to fire unnecessary calls. We need to set our hash values in code BUT ONLY trigger ajax calls when the user hits the next or back browser buttons.
var latestHash
function hashHistory(event){
var el = $(event.target)
var hh = el.attr('history')
historyMap.setItem( hh, event );
// this is set to prevent double-calling.
// when hashchange is triggered outside here, a call is fired.
latestHash = hh;
window.location.hash = hh;
}
The tricky thing to grasp is that the history map actually saves the click events that were triggered. This allows complex events to run; the whole stage can change. Compare this to simpler implementations that save a "url" to navigate to. I wince at the comparison.
$(document).ready(function() {
$(window).hashchange( function(){
var hash = location.hash.replace( /^#/, '' );
// DO NOT issue calls when the hash was set by code
if (hash == latestHash) return;
latestHash = hash;
if (historyMap.hasItem(hash)) {
ajaxClick( historyMap.getItem(hash) );
// as if the user clicked the link
} else {
var el = $('[history='+hash+']')
if (el){
el.click();
// which should also fire ajaxClick();
}
}
})
// Now make sure any initial hashes are respected
// This allows bookmarks on hash values to work
$(window).hashchange();
})
To make any link enforce its history we provide a custom attribute on that link. We simple add (history="my-hash") to the
Finally. A solution that keeps record of any notable changes in the application and offers a history based on events.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.