//// DEVELOPER INFO: jose@jcao.com http://jcao.com


//// HANDLES QUERYSTRINGS
	function queryHandler() {
		var classRoot = this;
		classRoot.values = new Array();
	// populate the values array
		classRoot.getValues = function() {
			var querystring   = document.location.search;
			classRoot.values.length = 0;
			if (querystring) {
				if (querystring.charAt(0) == '?') { querystring = querystring.substring(1, querystring.length); }
				// loop through pairs and assign them in the array
				for (loop = 0; loop < querystring.split('&').length; loop++) {
					var thisPair = querystring.split('&')[loop];
					var thisName = unescape(thisPair.split('=')[0]);
					var thisValue = unescape(thisPair.split('=')[1]);
					classRoot.values[thisName] = thisValue;
				}
			}
		}
	// get a querystring variable value
		classRoot.get = function(getValue) {
			classRoot.getValues();
			return classRoot.values[getValue];
		}
		classRoot.getValues();
	}


//// HANDLES COOKIES
	function cookieHandler() {
		var classRoot = this;
		classRoot.values = new Array();
	// populate the values array
		classRoot.getValues = function() {
			var cookieString   = document.cookie;
			classRoot.values.length = 0;
			if (cookieString) {
			// loop through pairs and assign them in the array
				for (var loop = 0; loop < cookieString.split('; ').length; loop++) {
					var thisPair = cookieString.split('; ')[loop];
					var thisName = unescape(thisPair.split('=')[0]);
					var thisValue = unescape(thisPair.split('=')[1]);
					classRoot.values[thisName] = thisValue;
				}
			}
		}
	// write a cookie, for 'expires' pass it a date (Month Day, 4-digit-year), or a number (days until expiration).
		classRoot.write = function(cookieName, cookieValue, expires, path) {
			cookieValue   = cookieName + '=' + escape(cookieValue);
			var cookieExpires = '';
			// date handling could be much more precise but this will do for now  ...
			if (expires) {
				// Assume expires is a Date
				var cookieDate  = new Date(expires).toGMTString();
				// if date is invalid, assume expires is a number, representing days to expire in
				if (expires) {
					var futureDate = new Date();
					futureDate.setTime(futureDate.getTime()+(expires*24*60*60*1000));
					cookieDate = futureDate.toGMTString();
				}
				cookieValue+= ';expires=' + cookieDate;
			}
			if (path) { cookieValue+= path; }
			document.cookie = cookieValue;
			classRoot.getValues();
		}
	// expire a cookie
		classRoot.expire = function(cookieName) {
			classRoot.write(cookieName, 'false', 'April 1, 1976');
		}
	// get a cookie value
		classRoot.get = function(getValue) {
			classRoot.getValues();
			return (classRoot.values[getValue]) ? classRoot.values[getValue] : false;
		}
		classRoot.getValues();
	}

//// HANDLES XMLHTTP:
//// asynchronously: ajaxReq('test.txt' , callbackFunction, ['suzy', 'jane']); ---> callbackFunction(httpResponse, 'suzy', 'jane'); 
//// synchronously var httpResponse = ajaxReq('test.txt');
//// args argument can handle up to 10 arguments for the callback function. this can be edited in the onreadystatechange handler.
//// DEVELOPER INFO: jose@jcao.com http://jcao.com
	function ajaxReq(url, callback, args) {
	// don't assume this is supported
		var xmlhttp = false;
	// determine data type
		var datType = 'text/txt'; // default data type is text.
			if (/\.xml$/.test(url.split('?')[0]))  { datType = 'text/xml';        }
			if (/\.txt$/.test(url.split('?')[0]))  { datType = 'text/txt';        }
			if (/\.js$/.test(url.split('?')[0]))   { datType = 'text/javascript'; }
			if (/\.json$/.test(url.split('?')[0])) { datType = 'text/javascript'; }
		var isXml = (url.split('?')[0].substring(url.split('?')[0].lastIndexOf('.')) == '.xml') ? true:false ;
	// set up request object
		if (typeof(ActiveXObject) != 'function' && typeof(XMLHttpRequest) != 'undefined') {
			xmlhttp = new XMLHttpRequest();
			if (xmlhttp.overrideMimeType && isXml) { xmlhttp.overrideMimeType(datType); }
		} else {
			try {
				xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
			}
		}
	// return support feedback, assuming a call with no url is a test.
		if (!xmlhttp) { return false; } else if (!url) { return true; }
	// handle results, asynchronously through a callback function, or
	// synchronously as a returned value if no callback is passed.
		if (callback) {
			// if callback, make asynchronous request
			xmlhttp.onreadystatechange = function() {
				if(xmlhttp.readyState == 4) {
					var serverResponse = (!isXml) ? xmlhttp.responseText : xmlhttp.responseXML;
					if (!newArgs) { var newArgs = new Array(); }                                                      // if !args, make an array to store them
					newArgs[0] = (datType == 'text/javascript') ? eval(serverResponse) : serverResponse;              // handle response, put it first
					if(args) { for(var loop = 1; loop <= args.length; loop++)   { newArgs[loop] = args[loop-1]; } }   // append arg values or null if !arg
					for (loop = newArgs.length; loop < 11; loop++)  { newArgs[loop] = 'undefined'; }
					callback(newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8], newArgs[9], newArgs[10]);
				}
			}
			xmlhttp.open('GET', url, true);
			xmlhttp.send(null);
			return true;
		} else {
			// if !callback, make synchronous request
			xmlhttp.open('GET', url, false);
			xmlhttp.send(null);
				if (xmlhttp.status == 200) {
					var serverResponse = (!isXml) ? xmlhttp.responseText : xmlhttp.responseXML;
					if (datType == 'text/javascript') { serverResponse = eval(serverResponse); }
				} else {
					var serverResponse = false;
				}
			return serverResponse;
		}
	}


//// OBJECT INITIATION
var qrystr = new queryHandler();
var cookie = new cookieHandler();