		//// BEGIN HEADER ////////////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////////////////////////////
		////                                                                                          ////
		////    xmlhttpHandler CLASS.                                                                 ////
		////                                                                                          ////
		////    Copyright 2006, Jose Cao-Garcia                                                       ////
		////                                                                                          ////
		////    This software is licensed under the Creative Commons                                  ////
		////    Attribution-ShareAlike 2.5 License:                                                   ////
		////    <http://creativecommons.org/licenses/by-sa/2.5/legalcode>                             ////
		////                                                                                          ////
		////    HELP/INFO/DEVELOPER CONTACT: jose@jcao.com, http://jcao.com                           ////
		////                                                                                          ////
		//////////////////////////////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////////////////////////////
		////                                                                                          ////
		////    DOCUMENTATION FORTHCOMING ...                                                         ////
		////                                                                                          ////
		//////////////////////////////////////////////////////////////////////////////////////////////////
		//// END HEADER //////////////////////////////////////////////////////////////////////////////////

		//// class for handling xmlhttp requests
		function xmlHttpHandler(delay) {
		// gather scope
			var root = this;
		// array for queing requests
			root.requests = [];
		// root.delay
			root.delay = (delay && typeof(delay) == 'number') ? delay : 50;
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// SELECT XMLHTTP OBJECT BY BROWSER CAPABILITIES                                           ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.xmlHttp = function() {
			// do not assume this is supported
				var xmlHttp = false;
			// select object by object support
				if (typeof(ActiveXObject) != 'function' && typeof(XMLHttpRequest) != 'undefined') {
				// for standards based browsers
					xmlHttp = new XMLHttpRequest();
				} else {
				// for standards-challenged browsers ...
					try {
						xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
					} catch (e) {
						xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
					}
				}
				return xmlHttp;
			}
			root.supported = (root.xmlHttp) ? true : false;
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// DETERMINE CONTENT TYPE.                                                                 ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.getType = function(request) {
			// default type is text
				var datType = 'text/txt';
			// test for some basic data types
				if      (/\.xml$/.test(request.split('?')[0]))  { datType = 'text/xml';        }
				else if (/\.js$/.test(request.split('?')[0]))   { datType = 'text/javascript'; }
				else if (/\.json$/.test(request.split('?')[0])) { datType = 'text/javascript'; }
			// report back
				return datType;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// QUE NEW REQUEST FOR HANDLING                                                            ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.get = function(request, callback, args) {
				if (callback) {
					root.requests.push([request, callback, args]);
					if (root.requests.length == 1) { root.start(); }
					return root.supported;
				} else {
					return root.sendRequest([request]);
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// MAKES HTTP REQUEST, HANDLES RESPONSE, SENDS RESPONSE TO CALLBACK FUNCTION               ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.sendRequest = function(requestData, fromQueue) {
			// get the basics
				var xmlHttp = root.xmlHttp();
				var request = requestData[0];
				var handler = (typeof(requestData[1]) == 'function') ? requestData[1] : false;
				var args    = (typeof(requestData[2]) == 'object')   ? requestData[2] : [];
			// if supported, handle request
				if (xmlHttp) {
					var datType = root.getType(request);
					if (xmlHttp.overrideMimeType && datType == 'text/xml') { xmlHttp.overrideMimeType(datType); }
				// handle request, asynchronously or synchronously
					if (handler) {
					// if callback, make asynchronous request
						xmlHttp.onreadystatechange = function() {
							if(xmlHttp.readyState == 4) {
							// handle the server response
								var serverResponse = (datType != 'text/xml') ? xmlHttp.responseText : xmlHttp.responseXML;
								serverResponse = (datType == 'text/javascript') ? eval(serverResponse) : serverResponse;
							// insert response into args array
								args.unshift(serverResponse);
							// create string to evaluate as arguments obj from args
								var argStr = '';
								for (var arg in args) { argStr += 'args[' + arg + '], ' };
								argStr = argStr.substring(0, argStr.lastIndexOf(','));
							// if request came from queue, remove it
								if (fromQueue) { root.start(); }
							// send response to callback function ...
							// eval is bad but I think it's the only way here 
								eval('handler(' + argStr + ')');
							}
						}
						xmlHttp.open('GET', request, true);
						xmlHttp.send(null);
						return true;
					} else {
					// if !callback, make synchronous request
						xmlHttp.open('GET', request, false);
						xmlHttp.send(null);
						if (xmlHttp.status == 200) {
							var serverResponse = (datType == 'text/javascript') ? xmlHttp.responseText : xmlHttp.responseXML;
							if (datType == 'text/javascript') { serverResponse = eval(serverResponse); }
							return serverResponse;
						}
					}
				} else {
					return false;
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// REMOVES AND FIRES A SINGLE REQUEST FROM THE REQUESTS QUEUE                              ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.start = function() {
				if (root.requests.length > 0) {
					var nextRequest = function() {
						var request = root.requests.shift();
						root.sendRequest(request, true);
					}
				// put slight delay on request
					root.timer = setTimeout(nextRequest, root.delay);
				}
			}
		}


		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// A SIMPLE CLASS THAT PROVIDES EASY QUERYSTRING READING AND CREATION TOOLS                ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			function queryHandler(url) {
			// scope
				var root = this;
			// function returns complete urlencoded querystring for instance
				root.tostring = function() {
					var objs = 0;
					var qstr = (url) ? url.split('?')[0]+'?' : '?';
					for (var loop in root) {
						if (objs > 0) {
							qstr += escape(loop) + '=' + escape(root[loop]) + '&';
						}
						objs++;
					}
					return qstr.substring(0, qstr.lastIndexOf('&'));
				}
			// dump pairs into object as properties
				if (url) {
				// remove ? and split.


					qstr =  (url.indexOf('?') != -1) ? qstr = url.split('?')[1].split('&') : [];


				// loop and add objects
					for (var loop in qstr) {
						var thisPair = qstr[loop].split('=');
						root[thisPair[0]] = thisPair[1]
					}
				}
			}


		//// 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();
			}



		//// OBJECT INITIATION
			var qrystr = new queryHandler(document.location.href);
			var cookie = new cookieHandler();
			var ajax   = new xmlHttpHandler(50);
