/**
 *  HistMan - Javascript History Manager v0.2 for Prototype 1.5.0
 *  -------------------------------------------------------------
 *  HistMan adds history and bookmarking support to ajax/javascript driven
 *  applications. HistMan's tested and known to work on IE6, IE7, FF2 and Opera9.
 *  HistMan needs Prototype v1.5.0 to run. For more information, see
 *  <http://www.solutoire.com/histman>
 *
 *
 *	Copyright
 *	---------
 *	Copyright 2007 (c) Bas Wenneker <b.wenneker+spamme[a]gmail[d]com>
 *	For use under the BSD license. <http://www.solutoire.com/histman>
 */

var HistMan = function(){

//key:value pairs -> (location hash):(history object)
var registry = {};
//previous location hash
var pHash = '';
//path/to/<server_side_script>
var scriptUri;
//default callback function
var callback;

return {
	/**
	 * Current location hash.
	 */
	cHash: '',

	/**
	 * HistMan.start() initializes the history manager.
	 *
	 * @param {String} uri		- Location of the serverside script.
	 * @param {String} callback	- Default callback function.
	 * @param {Array} elements	- Elements having the 'history' attribute set.
	 */
	start: function(uri, fn, elements){
		HistMan.parse(elements || HistMan.getElements('history'));

		callback = fn || 'alert';
		scriptUri = uri || '';
		cHash = HistMan.getHash() || '';

		if(!document.all){
			(function(){
				cHash = HistMan.getHash();
				if(cHash !== '' && pHash != cHash){
					pHash = cHash;
					HistMan.doCallback();
				}
			}).periodical(200);
		} else {
			var iframe = document.createElement('iframe');
			with(iframe){
				width = '1';
				height = '1';
				frameBorder = '0';
				name = '_histman___';
				id = '_histman___';
			}
			document.appendChild(iframe);

			if(cHash !== '') HistMan.add(cHash);
		}
	},

	/**
	 * This function registrates an element in the
	 * HistMan registry.
	 *
	 * @param {Element} element - Element to register
	 * @param {Object} obj - History Object
	 */
	register: function(element, obj){
		var key = (obj.hash) ? obj.hash : obj.arg;
//		if(registry[key]) throw 'Tried to register a key that already exists!';
		registry[key] = {arg:obj.arg, callback: (obj.callback || false)};

		element.addEvent('click',function(e){
			new Event(e).stop();
			HistMan.add(key);
		});
	},

	/**
	 * HistMan.add() adds a new entry in the window.history Array. This
	 * function enables the backbutton.
	 *
	 * @param {String} key	- Key of a history object in the registry.
	 */
	add: function(key){
		if(!key) return;
		if(!document.all) window.location.hash = 'h_'+key;
		else frames['_histman___'].location.href = scriptUri + "?arg=" + registry[key].arg + "&hash=" + key;
	},

	/**
	 * This function is called when a history link is clicked
	 * or when the page is refreshed/loaded. When the history link
	 * has a custom callback function set then that function is called,
	 * otherwise the default callback function is called.
	 *
	 * @param {String} arg	- Argument for the callback function.
	 */
	doCallback: function(arg){
		var obj = registry[HistMan.getHash()];
		window[obj.callback || callback](arg || obj.arg);
	},

	/**
	 * Histman.parse() parses elements with a history
	 * attribute set. The history data is added to
	 * the registry. Also an onclick eventhandler is added to
	 * each element in the Array.
	 */
	parse: function(elements){
		HistMan.getElements('history').each(function(el){
			var attr = el.getProperty('history');
			eval('var obj = ' + attr);
			HistMan.register(el,obj);
		});
	},

	/**
	 * HistMan.getHash() returns the location hash without the
	 * history prefix '#h_'.
	 */
	getHash: function(){
		return window.location.hash.replace('#h_','');
	},

	/**
	 * This function returns all elements with an history attribute set.
	 *
	 * @param {String} attribute - attribute where looking for
	 * @param {String} parentElement - parent element
	 */
	getElements: function(attribute, parentElement) {
//		var children = ($(parentElement) || document.body).getElementsByTagName('*');
//		return $A(children).filter(function(el) {
//			return ($(el).getProperty(attribute));
//	  	});
    return $$('.history');
	}
};}()