function Ajax(url, callback)
{
	// basic properties
	this.url = url;
	this.callback = callback;
	this.callbackArguments = arguments;
	this.useXml = false;
	this.formData = null;
	this.onerror = null;

	// methods
	this.Fetch = ajaxFetch;

	// XmlHttpRequest object
	this.request = null;
}

function ajaxFetch()
{
    var request = this.request;
    var callback = this.callback;
    var callbackArguments = this.callbackArguments;
    var formData = this.formData;
    var onerror = this.onerror;
    var useXml = this.useXml;

    // branch for native XMLHttpRequest object
    if(window.XMLHttpRequest) {
    	try {
			request = new XMLHttpRequest();
        } catch(e) {
			request = null;
        }
    // branch for IE/Windows ActiveX version
    } else if(window.ActiveXObject) {
       	try {
        	request = new ActiveXObject("Msxml2.XMLHTTP");
      	} catch(e) {
        	try {
          		request = new ActiveXObject("Microsoft.XMLHTTP");
        	} catch(e) {
          		request = null;
        	}
		}
    }

	if(request) {
		request.onreadystatechange = function () {
										if(request.readyState == 4) {
											if(request.status == 200) {
												if(callback != null) {
													// we replace the second argument (callback function) with the xhr object)
													// kind of cheesy, but it is nice and easy and works well
													callbackArguments[1] = request;
													callback.apply(this, callbackArguments);
												}
											} else {
												if(onerror) {
													onerror();
												}
												else {
													alert("There was a problem retrieving the XML data:\n" + request.responseText);
												}
											}

											// clean up
											request = null;
										}
									}
		var method = (formData != null ? "POST" : "GET");
		var contentType = (formData != null ? "application/x-www-form-urlencoded" : "text/plain");
		var data = (formData != null ? formData : "");
		request.open(method, this.url, true);
		request.setRequestHeader("Content-Type", contentType);
		request.send(data);
	}
}

String.prototype.endsWith = function(s){
	var reg = new RegExp(s + "$");
	return reg.test(this);
}



var Cookie = function(){
	return {
		createCookie : function(name,value,days) {
			if (days) {
				var date = new Date();
				date.setTime(date.getTime()+(days*24*60*60*1000));
				var expires = "; expires="+date.toGMTString();
			}
			else var expires = "";
			document.cookie = name+"="+value+expires+"; path=/";
		},
		
		readCookie : function(name) {
			var nameEQ = name + "=";
			var ca = document.cookie.split(';');
			for(var i=0;i < ca.length;i++) {
				var c = ca[i];
				while (c.charAt(0)==' ') c = c.substring(1,c.length);
				if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
			}
			return null;
		},
		
		eraseCookie : function(name) {
			this.createCookie(name,"",-1);
		}
	}
}();

var Hashtable = function(){
	var hashtable = new Array();

	return {
		clear : function(){
			hashtable = new Array();
		},

		containsKey : function(key){
			var exists = false;
			for (var i in hashtable) {
				if (i == key && hashtable[i] != null) {
					exists = true;
					break;
				}
			}
			return exists;
		},
		
		containsKey : function(key){
			var exists = false;
			for (var i in hashtable) {
				if (i == key && hashtable[i] != null) {
					exists = true;
					break;
				}
			}
			return exists;
		},
		
		containsValue : function(value){
			var contains = false;
			if (value != null) {
				for (var i in hashtable) {
					if (hashtable[i] == value) {
						contains = true;
						break;
					}
				}
			}
			return contains;
		},
		
		get : function(key){
			return hashtable[key];
		},
		
		isEmpty : function(){
			return (parseInt(this.size()) == 0) ? true : false;
		},
		
		keys : function(){
			var keys = new Array();
			for (var i in hashtable) {
				if (hashtable[i] != null) 
					keys.push(i);
			}
			return keys;
		},
		
		put : function(key, value){
			if (key == null || value == null) {
				throw "NullPointerException {" + key + "},{" + value + "}";
			}else{
				hashtable[key] = value;
			}
		},
		
		remove : function(key){
			var rtn = hashtable[key];
			hashtable[key] = null;
			return rtn;
		}, 
		
		size : function(){
			var size = 0;
			for (var i in hashtable) {
				if (hashtable[i] != null) 
					size ++;
			}
			return size;
		},
		
		toString : function(){
			var result = "";
			for (var i in hashtable)
			{      
				if (hashtable[i] != null) 
					result += "{" + i + "},{" + hashtable[i] + "}\n";   
			}
			return result;
		},
		
		getValues : function(){
			var values = new Array();
			for (var i in hashtable) {
				if (hashtable[i] != null) 
					values.push(hashtable[i]);
			}
			return values;
		}
	}
};

window.onDomReady = function(fn){
	this._timer = null;
	
	var init = function() {
		// quit if this function has already been called
		if (arguments.callee.done) return;    
		// flag this function so we don't do the same thing twice    
		arguments.callee.done = true;    
		// kill the timer    
		if (arguments.callee._timer) clearInterval(arguments.callee._timer);    
		// do stuff
		fn();
	};

	/* for Mozilla/Opera9 */
	if (document.addEventListener) {
		document.addEventListener("DOMContentLoaded", init, false);
	}
	/* for Internet Explorer */
	/*@cc_on @*/
	/*@if (@_win32)
		document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");    
		var script = document.getElementById("__ie_onload");    
		script.onreadystatechange = function() {
			if (this.readyState == "complete") {
				init(); // call the onload handler
			}
		};
	/*@end @*/
	/* for Safari */
	if (/WebKit/i.test(navigator.userAgent)) { // sniff    
		_timer = setInterval(function() {
			if (/loaded|complete/.test(document.readyState)) {            
				init(); // call the onload handler
			}
		}, 10);
	}
	/* for other browsers */
	window.onload = init;
};
