function handleLocations(callback) {
	mode = 'sync';
	if (callback) { mode = 'async'; }
	this.className = 'handleLocations';
	this.dispatcher = new HTML_AJAX_Dispatcher(this.className,mode,callback,'/libs/ajax/ajaxServer.php?','JSON');
}
handleLocations.prototype  = {
	Sync: function() { this.dispatcher.Sync(); }, 
	Async: function(callback) { this.dispatcher.Async(callback); },
	getGeoIPLocation: function() { return this.dispatcher.doCall('getGeoIPLocation',arguments); },
	isDefaultLocation: function() { return this.dispatcher.doCall('isDefaultLocation',arguments); }
}

// Compat.js
/**
 * Compat functions
 * @category	HTML
 * @package	AJAX
 * @author	Joshua Eichorn <josh@bluga.net>
 * @copyright	2005 Joshua Eichorn
 * @license	http://www.opensource.org/licenses/lgpl-license.php  LGPL
 */
if (!String.fromCharCode && !String.prototype.fromCharCode) {
	String.prototype.fromCharCode = function(code)
	{
		var h = code.toString(16);
		if (h.length == 1) {
			h = '0' + h;
		}
		return unescape('%' + h);
	}
}
if (!String.charCodeAt && !String.prototype.charCodeAt) {
	String.prototype.charCodeAt = function(index)
	{
		var c = this.charAt(index);
		for (i = 1; i < 256; i++) {
			if (String.fromCharCode(i) == c) {
				return i;
			}
		} 
	}
}

if (!Array.splice && !Array.prototype.splice) {
	Array.prototype.splice = function(s, d)
	{
		var max = Math.max,
		min = Math.min,
		a = [],
		e,
		i = max(arguments.length - 2, 0),
		k = 0,
		l = this.length,
		n,
		v,
		x;

		s = s || 0;
		if (s < 0) {
			s += l;
		}
		s = max(min(s, l), 0);
		d = max(min(typeof d == 'number' ? d : l, l - s), 0);
		v = i - d;
		n = l + v;
		while (k < d) {
			e = this[s + k];
			if (!e) {
				a[k] = e;
			}
			k += 1;
		}
		x = l - s - d;
		if (v < 0) {
			k = s + i;
			while (x) {
				this[k] = this[k - v];
				k += 1;
				x -= 1;
			}
			this.length = n;
		} else if (v > 0) {
			k = 1;
			while (x) {
				this[n - k] = this[l - k];
				k += 1;
				x -= 1;
			}
		}
		for (k = 0; k < i; ++k) {
			this[s + k] = arguments[k + 2];
		}
		return a;
	}
}
if (!Array.push && !Array.prototype.push) {
	Array.prototype.push = function()
	{
		for (var i = 0, startLength = this.length; i < arguments.length; i++) {
			this[startLength + i] = arguments[i];
		}
		return this.length;
	}
}
if (!Array.pop && !Array.prototype.pop) {
	Array.prototype.pop = function()
	{
		return this.splice(this.length - 1, 1)[0];
	}
}
/*
	From IE7, version 0.9 (alpha) (2005-08-19)
	Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
*/
if (!DOMParser.parseFromString && window.ActiveXObject)
{
function DOMParser() {/* empty constructor */};
DOMParser.prototype = {
	parseFromString: function(str, contentType) {
		var xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
		xmlDocument.loadXML(str);
		return xmlDocument;
	}
};

function XMLSerializer() {/* empty constructor */};
XMLSerializer.prototype = {
	serializeToString: function(root) {
		return root.xml || root.outerHTML;
	}
};
}
// Main.js
/**
 * JavaScript library for use with HTML_AJAX
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category	HTML
 * @package	Ajax
 * @author	Joshua Eichorn <josh@bluga.net>
 * @author	Arpad Ray <arpad@php.net>
 * @author	David Coallier <davidc@php.net>
 * @author	Elizabeth Smith <auroraeosrose@gmail.com>
 * @copyright	2005 Joshua Eichorn, Arpad Ray, David Coallier, Elizabeth Smith
 * @license	http://www.opensource.org/licenses/lgpl-license.php  LGPL
 */
var HTML_AJAX = {
	version: '0.5.2',
	defaultServerUrl: false,
	defaultEncoding: 'JSON',
	queues: false,
	clientPools: {},

	httpClient: function(name) {
		if (name) {
			if (this.clientPools[name]) {
				return this.clientPools[name].getClient();
			}
		}
		return this.clientPools['default'].getClient();
	},

	makeRequest: function(request) {
		if (!HTML_AJAX.queues[request.queue]) {
			var e = new Error('Unknown Queue: '+request.queue);
			if (HTML_AJAX.onError) {
				HTML_AJAX.onError(e);
				return false;
			}
			else {
				throw(e);
			}
		}
		else {
			var qn = request.queue;
			var q = HTML_AJAX.queues[qn];

			HTML_AJAX.queues[request.queue].addRequest(request);
			return HTML_AJAX.queues[request.queue].processRequest();
		}
	},

	serializerForEncoding: function(encoding) {
		for(var i in HTML_AJAX.contentTypeMap) {
			if (encoding == HTML_AJAX.contentTypeMap[i] || encoding == i) {
				return eval("new HTML_AJAX_Serialize_"+i+";");
			}
		}
		return new HTML_AJAX_Serialize_Null();
	},
	fullcall: function(url,encoding,className,method,callback,args, options) {
		var serializer = HTML_AJAX.serializerForEncoding(encoding);

		var request = new HTML_AJAX_Request(serializer);
		if (callback) {
			request.isAsync = true;
		}
		request.requestUrl = url;
		request.className = className;
		request.methodName = method;
		request.callback = callback;
		request.args = args;
		if (options) {
			for(var i in options) {
				request[i] = options[i];
			}
			if (options.grab) {
				if (!request.args || !request.args.length) {
					request.requestType = 'GET';
				}
			}
		}

		return HTML_AJAX.makeRequest(request);
	},
	callPhpCallback: function(phpCallback, jsCallback, url) {
		var args = new Array();
		for (var i = 3; i < arguments.length; i++) {
			args.push(arguments[i]);
		}
		if (HTML_AJAX_Util.getType(phpCallback[0]) == 'object') {
			jsCallback(phpCallback[0][phpCallback[1]](args));
			return;
		}
		if (!url) {
			url = HTML_AJAX.defaultServerUrl;
		}
		HTML_AJAX.fullcall(url, HTML_AJAX.defaultEncoding,
			false, false, jsCallback, args, {phpCallback: phpCallback});
	},
	call: function(className,method,callback) {
		var args = new Array();
		for(var i = 3; i < arguments.length; i++) {
			args.push(arguments[i]);
		}
		return HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,className,method,callback,args);
	},
	grab: function(url,callback,options) {
		if (!options) {
			options = {grab:true};
		}
		else {
			options['grab'] = true;
		}
		return HTML_AJAX.fullcall(url,'Null',false,null,callback, '', options);
	},
	post: function(url,payload,callback,options) {
		var serializer = 'Null';
		if (HTML_AJAX_Util.getType(payload) == 'object') {
			serializer = 'Urlencoded';
		}
		return HTML_AJAX.fullcall(url,serializer,false,null,callback, payload, options);
	},
	replace: function(id) {
		var callback = function(result) {
			HTML_AJAX_Util.setInnerHTML(HTML_AJAX_Util.getElement(id),result);
		}
		if (arguments.length == 2) {
			HTML_AJAX.grab(arguments[1],callback);
		}
		else {
			var args = new Array();
			for(var i = 3; i < arguments.length; i++) {
				args.push(arguments[i]);
			}
			HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,arguments[1],arguments[2],callback,args, {grab:true});
		}
	},
	append: function(id) {
		var callback = function(result) {
			HTML_AJAX_Util.setInnerHTML(HTML_AJAX_Util.getElement(id),result,'append');
		}
		if (arguments.length == 2) {
			HTML_AJAX.grab(arguments[1],callback);
		}
		else {
			var args = new Array();
			for(var i = 3; i < arguments.length; i++) {
				args.push(arguments[i]);
			}
			HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,arguments[1],arguments[2],callback,args, {grab:true});
		}
	}, 
	Open: function(request) {
	},
	Load: function(request) {
	},
	contentTypeMap: {
		'JSON':			'application/json',
		'Null':			'text/plain',
		'Error':		'application/error',
		'PHP':			'application/php-serialized',
		'HA' :			'application/html_ajax_action',
		'Urlencoded':	'application/x-www-form-urlencoded'
	},
	requestComplete: function(request,error) {
		for(var i in HTML_AJAX.queues) {
			if (HTML_AJAX.queues[i].requestComplete) {
				HTML_AJAX.queues[i].requestComplete(request,error);
			}
		}
	},
	formEncode: function(form, array_format) {
		form = HTML_AJAX_Util.getElement(form);
		var el, inpType, value, name;
		var out = (array_format) ? {} : '';
		var inputTags = form.getElementsByTagName('INPUT');
		var selectTags = form.getElementsByTagName('SELECT');
		var buttonTags = form.getElementsByTagName('BUTTON');
		var textareaTags = form.getElementsByTagName('TEXTAREA');
		var arrayRegex = /(.+)%5B%5D/;

		var validElement = function (element) {
			if (!element || !element.getAttribute) {
				return false;
			}
			el = element;
			name = HTML_AJAX_Util.encodeUrl(el.getAttribute('name'));
			if (!name) {
				return false;
			}
			if (element.disabled) {
				return false;
			}
			
			if (!array_format) {
				value = HTML_AJAX_Util.encodeUrl(el.value);
			} else {
				value = el.value;
			}
			
			inpType = el.getAttribute('type');
			return true;
		}
		
		inputLoop:
		for (var i=0; i < inputTags.length; i++) {
			if (!validElement(inputTags[i])) {
				continue;
			}
			if (inpType == 'checkbox' || inpType == 'radio') {
				if (!el.checked) {
					continue inputLoop;
				}
				var arr_var = arrayRegex.exec(name); 
				if (array_format && arr_var) {
					if (!out[arr_var[1]]) {
						out[arr_var[1]] = new Array();
					}
					out[arr_var[1]].push(value);
					continue inputLoop;
				}
			}
			if (array_format) {
				out[name] = value;
			} else {
				out += name + '=' + value + '&';
			}
		}

		selectLoop:
		for (var i=0; i<selectTags.length; i++) {
			if (!validElement(selectTags[i])) {
				continue selectLoop;
			}
			var options = el.options;
			for (var z=0; z<options.length; z++){
				var option=options[z];
				if(option.selected){
					if (array_format) {
						if (el.type == 'select-one') {
							out[name] = option.value;
							continue selectLoop;
						} else {
							if (!out[name]) {
								out[name] = new Array();
							}
							out[name].push(option.value);
						}
					} else {
						out += name + '=' + option.value + '&';
						if (el.type == 'select-one') {
							continue selectLoop;
						}
					}
				}
			}
		}

		buttonLoop:
		for (var i=0; i<buttonTags.length; i++) {
			if (!validElement(buttonTags[i])) {
				continue;
			}
			if (array_format) {
				out[name] = value;
			} else {
				out += name + '=' + value + '&';
			}
		}

		textareaLoop:
		for (var i=0; i<textareaTags.length; i++) {
			if (!validElement(textareaTags[i])) {
				continue;
			}
			if (array_format) {
				out[name] = value;
			} else {
				out += name + '=' + value + '&';
			}
		} 
		
		return out;
	},
	formSubmit: function (form, target, options)
	{
		form = HTML_AJAX_Util.getElement(form);
		if (!form) {
			return false;
		}

		var out = HTML_AJAX.formEncode(form);
		target = HTML_AJAX_Util.getElement(target);
		if (!target) {
			target = form;
		}
		try
		{
			var action = form.attributes['action'].value;
		}
		catch(e){}
		if(action == undefined)
		{
			action = form.getAttribute('action');
		}

		var callback = false;
		if (HTML_AJAX_Util.getType(target) == 'function') {
			callback = target;
		}
		else {
			callback = function(result) {
				if (typeof result != 'undefined') {
					HTML_AJAX_Util.setInnerHTML(target,result);
				}
			}
		}

		var serializer = HTML_AJAX.serializerForEncoding('Null');
		var request = new HTML_AJAX_Request(serializer);
		request.isAsync = true;
		request.callback = callback;

		switch (form.getAttribute('method').toLowerCase()) {
		case 'post':
			var headers = {};
			headers['Content-Type'] = 'application/x-www-form-urlencoded';
			request.customHeaders = headers;
			request.requestType = 'POST';
			request.requestUrl = action;
			request.args = out;
			break;
		default:
			if (action.indexOf('?') == -1) {
				out = '?' + out.substr(0, out.length - 1);
			}
			request.requestUrl = action+out;
			request.requestType = 'GET';
		}

		if(options) {
			for(var i in options) {
				request[i] = options[i];
			}
		}
		HTML_AJAX.makeRequest(request);
		return true;
	},
	makeFormAJAX: function(form,target,options) {
		form = HTML_AJAX_Util.getElement(form);
		var preSubmit = false;
		if(typeof form.onsubmit != 'undefined') {
			preSubmit = form.onsubmit;
			form.onsubmit = function() {};
		}
		form.HAOptions = options;
		var handler = function(e) {
			var form = HTML_AJAX_Util.eventTarget(e);

			var valid = true;
			if (preSubmit) {
				valid = preSubmit();
			}
			if (valid) {
				HTML_AJAX.formSubmit(form,target,form.HAOptions);
			}
			e.returnValue = false;
			if (e.preventDefault) {
				e.preventDefault();
			}
		}
		HTML_AJAX_Util.registerEvent(form,'submit',handler);
	}
}

function HTML_AJAX_Serialize_Null() {}
HTML_AJAX_Serialize_Null.prototype = {
	contentType: 'text/plain; charset=utf-8',
	serialize: function(input) {
		return new String(input).valueOf();
	},
	
	unserialize: function(input) {
		return new String(input).valueOf();	
	}
}

function HTML_AJAX_Serialize_XML() {}
HTML_AJAX_Serialize_XML.prototype = {
	contentType: 'application/xml; charset=utf-8',
	serialize: function(input) {
		var xml = '';
		if(typeof(input) == 'object' && input)
		{
			for (var i = 0;i<input.length;i++)
			{
				xml += new XMLSerializer().serializeToString(input[i]);
			}
		}
		return xml;
	},

	unserialize: function(input) {
		return input;
	}
}

function HTML_AJAX_Serialize_JSON() {}
HTML_AJAX_Serialize_JSON.prototype = {
	contentType: 'application/json; charset=utf-8',
	serialize: function(input) {
		return HTML_AJAX_JSON.stringify(input);
	},
	unserialize: function(input) {
		try {
			return eval('('+input+')');
		} catch(e) {
			return HTML_AJAX_JSON.parse(input);
		}
	}
}

function HTML_AJAX_Serialize_Error() {}
HTML_AJAX_Serialize_Error.prototype = {
	contentType: 'application/error; charset=utf-8',
	serialize: function(input) {
		var ser = new HTML_AJAX_Serialize_JSON();
		return ser.serialize(input);
	},
	unserialize: function(input) {
		var ser = new HTML_AJAX_Serialize_JSON();
		var data = new ser.unserialize(input);

		var e = new Error('PHP Error: '+data.errStr);
		for(var i in data) {
			e[i] = data[i];
		}
		throw e;
	}
}

function HTML_AJAX_Queue_Immediate() {}
HTML_AJAX_Queue_Immediate.prototype = {
	request: false,
	addRequest: function(request) {
		this.request = request;
	},
	processRequest: function() {
		var client = HTML_AJAX.httpClient();
		client.request = this.request;
		return client.makeRequest();
	}
}

HTML_AJAX.queues = new Object();
HTML_AJAX.queues['default'] = new HTML_AJAX_Queue_Immediate();

// Queue.js
/**
 * Various processing queues, use when you want to control how multiple requests are made
 * @category	HTML
 * @package	AJAX
 * @author	Joshua Eichorn <josh@bluga.net>
 * @copyright	2005 Joshua Eichorn
 * @license	http://www.opensource.org/licenses/lgpl-license.php  LGPL
 */

function HTML_AJAX_Queue_Interval_SingleBuffer(interval,singleOutstandingRequest) {
	this.interval = interval;
	if (singleOutstandingRequest) {
		this.singleOutstandingRequest = true;
	}
}
HTML_AJAX_Queue_Interval_SingleBuffer.prototype = {
	request: false,
	_intervalId: false,
	singleOutstandingRequest: false,
	client: false,
	addRequest: function(request) {
		this.request = request;
	},
	processRequest: function() {
		if (!this._intervalId) {
			this.runInterval();
			this.start();
		}
	}, 
	start: function() {
		var self = this;
		this._intervalId = setInterval(function() { self.runInterval() },this.interval);
	},
	stop: function() {
		clearInterval(this._intervalId);
	},
	runInterval: function() {
		if (this.request) {
			if (this.singleOutstandingRequest && this.client) {
				this.client.abort();
			}
			this.client = HTML_AJAX.httpClient();
			this.client.request = this.request;
			this.request = false;
			this.client.makeRequest();
		}
	}
}

function HTML_AJAX_Queue_Ordered() { }
HTML_AJAX_Queue_Ordered.prototype = {
	request: false,
	order: 0,
	current: 0,
	callbacks: {},
	interned: {},
	addRequest: function(request) {
		request.order = this.order;
		this.request = request;
		this.callbacks[this.order] = this.request.callback;
		var self = this;
		this.request.callback = function(result) {
			self.processCallback(result,request.order);
		} 
	},
	processRequest: function() {
		var client = HTML_AJAX.httpClient();
		client.request = this.request;
		client.makeRequest();
		this.order++;
	},
	requestComplete: function(request,e) {
		if (e) {
			this.current++;
		}
	},
	processCallback: function(result,order) {
		if (order == this.current) {
			this.callbacks[order](result);
			this.current++;
		}
		else {
			this.interned[order] = result;
		}
		while (this.interned[this.current]) {
			this.callbacks[this.current](this.interned[this.current]);
			this.current++;
		}
}
}

function HTML_AJAX_Queue_Single() {
}
HTML_AJAX_Queue_Single.prototype = {
	request: false,
	client: false,
	addRequest: function(request) {
		this.request = request;
	},
	processRequest: function() {
		if (this.request) {
			if (this.client) {
				this.client.abort();
			}
			this.client = HTML_AJAX.httpClient();
			this.client.request = this.request;
			this.request = false;
			this.client.makeRequest();
		}
	}
}

/**
 * Priority queue
 *
 * @author	 Arpad Ray <arpad@php.net>
 */
function HTML_AJAX_Queue_Priority_Item(item, time) {
	this.item = item;
	this.time = time;
}
HTML_AJAX_Queue_Priority_Item.prototype = {
	compareTo: function (other) {
		var ret = this.item.compareTo(other.item);
		if (ret == 0) {
			ret = this.time - other.time;
		}
		return ret;
	}
}

function HTML_AJAX_Queue_Priority_Simple(interval) {
	this.interval = interval;   
	this.idleMax = 10;
	this.requestTimeout = 5;
	this.checkRetryChance = 0.1;
	this._intervalId = 0;
	this._requests = [];
	this._removed = [];
	this._len = 0;
	this._removedLen = 0;
	this._idle = 0;
}
HTML_AJAX_Queue_Priority_Simple.prototype = {
	isEmpty: function () {
		return this._len == 0;
	},
	addRequest: function (request) {
		request = new HTML_AJAX_Queue_Priority_Item(request, new Date().getTime());
		++this._len;
		if (this.isEmpty()) {
			this._requests[0] = request;
			return;
		}
		for (i = 0; i < this._len - 1; i++) {
			if (request.compareTo(this._requests[i]) < 0) {
				this._requests.splice(i, 1, request, this._requests[i]);
				return;
			}
		}
		this._requests.push(request);
	},
	peek: function () {
		return (this.isEmpty() ? false : this._requests[0]);
	},
	requestComplete: function (request) {
		for (i = 0; i < this._removedLen; i++) {
			if (this._removed[i].item == request) {
				this._removed.splice(i, 1);
				--this._removedLen;
				out('removed from _removed');
				return true;
			}
		}
		return false;
	},
	processRequest: function() {
		if (!this._intervalId) {
			this._runInterval();
			this._start();
		}
		this._idle = 0;
	},
	_runInterval: function() {
		if (Math.random() < this.checkRetryChance) {
			this._doRetries();
		}
		if (this.isEmpty()) {
			if (++this._idle > this.idleMax) {
				this._stop();
			}
			return;
		}
		var client = HTML_AJAX.httpClient();
		if (!client) {
			return;
		}
		var request = this.peek();
		if (!request) {
			this._requests.splice(0, 1);
			return;
		}
		client.request = request.item;
		client.makeRequest();
		this._requests.splice(0, 1);
		--this._len;
		this._removed[this._removedLen++] = new HTML_AJAX_Queue_Priority_Item(request, new Date().getTime());
	},
	_doRetries: function () {
		for (i = 0; i < this._removedLen; i++) {
			if (this._removed[i].time + this._requestTimeout < new Date().getTime()) {
				this.addRequest(request.item);
				this._removed.splice(i, 1);
				--this._removedLen;
				return true;
			}
		}
	},
	_start: function() {
		var self = this;
		this._intervalId = setInterval(function() { self._runInterval() }, this.interval);
	},
	_stop: function() {
		clearInterval(this._intervalId);
		this._intervalId = 0;
	}
};

HTML_AJAX_Client_Pool = function(maxClients, startingClients)
{
	this.maxClients = maxClients;
	this._clients = [];
	this._len = 0;
	while (--startingClients > 0) {
		this.addClient();
	}
}

HTML_AJAX_Client_Pool.prototype = {
	isEmpty: function()
	{
		return this._len == 0;
	},
	addClient: function()
	{
		if (this.maxClients != 0 && this._len > this.maxClients) {
			return false;
		}
		var key = this._len++;
		this._clients[key] = new HTML_AJAX_HttpClient();
		return this._clients[key];
	},
	getClient: function ()
	{
		for (var i = 0; i < this._len; i++) {
			if (!this._clients[i].callInProgress() && this._clients[i].callbackComplete) {
				return this._clients[i];
			}
		}
		var client = this.addClient();
		if (client) {
			return client;
		}
		return false;
	},
	removeClient: function (client)
	{
		for (var i = 0; i < this._len; i++) {
			if (!this._clients[i] == client) {
				this._clients.splice(i, 1);
				return true;
			}
		}
		return false;
	},
	clear: function ()
	{
		this._clients = [];
		this._len = 0;
	}
};

HTML_AJAX.clientPools['default'] = new HTML_AJAX_Client_Pool(0);

// Dispatcher.js
/**
 * Class that is used by generated stubs to make actual AJAX calls
 *
 * @category    HTML
 * @package 	AJAX
 * @author	Joshua Eichorn <josh@bluga.net>
 * @copyright   2005 Joshua Eichorn
 * @license 	http://www.opensource.org/licenses/lgpl-license.php  LGPL
 */
function HTML_AJAX_Dispatcher(className,mode,callback,serverUrl,serializerType) 
{
	this.className = className;
	this.mode = mode;
	this.callback = callback;
	this.serializerType = serializerType;

	if (serverUrl) {
		this.serverUrl = serverUrl
	}
	else {
		this.serverUrl = window.location;
	}
}

HTML_AJAX_Dispatcher.prototype = {
	queue: 'default',

	timeout: 20000,
 
	priority: 0,

	options: {},
	
	doCall: function(callName,args) 
	{
		var request = new HTML_AJAX_Request();
		request.requestUrl = this.serverUrl;
		request.className = this.className;
		request.methodName = callName;
		request.timeout = this.timeout;
		request.contentType = this.contentType;
		request.serializer = eval('new HTML_AJAX_Serialize_'+this.serializerType);
		request.queue = this.queue;
		request.priority = this.priority;

		for(var i in this.options) {
			request[i] = this.options[i];
		}
		
		for(var i=0; i < args.length; i++) {
			request.addArg(i,args[i]);
		};

		if ( this.mode == "async" ) {
			request.isAsync = true;
			if (this.callback[callName]) {
				var self = this;
				request.callback = function(result, request) { self.callback[callName](result, request); }
			}

		} else {
			request.isAsync = false;
		}

		return HTML_AJAX.makeRequest(request);
	},

	Sync: function() 
	{
		this.mode = 'sync';
	},

	Async: function(callback)
	{
		this.mode = 'async';
		if (callback) {
			this.callback = callback;
		}
	}
};
// HttpClient.js
/**
 * XMLHttpRequest Wrapper
 * @category    HTML
 * @package 	AJAX
 * @author      Joshua Eichorn <josh@bluga.net>
 * @copyright   2005 Joshua Eichorn
 * @license     http://www.opensource.org/licenses/lgpl-license.php  LGPL
 */
function HTML_AJAX_HttpClient() { }
HTML_AJAX_HttpClient.prototype = {
	request: null,

	_timeoutId: null,

	callbackComplete: true,

	aborted: false,
	
	init:function() 
	{
		try {
			this.xmlhttp = new XMLHttpRequest();
		} catch (e) {
			var XMLHTTP_IDS = new Array(
			'MSXML2.XMLHTTP.5.0',
			'MSXML2.XMLHTTP.4.0',
			'MSXML2.XMLHTTP.3.0',
			'MSXML2.XMLHTTP',
			'Microsoft.XMLHTTP' );
			var success = false;
			for (var i=0;i < XMLHTTP_IDS.length && !success; i++) {
				try {
					this.xmlhttp = new ActiveXObject(XMLHTTP_IDS[i]);
					success = true;
				} catch (e) {}
			}
			if (!success) {
				try{
					this.xmlhttp = new HTML_AJAX_IframeXHR();
					this.request.iframe = true;
				} catch(e) {
					throw new Error('Unable to create XMLHttpRequest.');
				}
			}
		}
	},

	callInProgress: function() 
	{
		switch ( this.xmlhttp.readyState ) {
			case 1:
			case 2:
			case 3:
				return true;
			break;
			default:
				return false;
			break;
		}
	},

	makeRequest: function() 
	{
		if (!this.xmlhttp) {
			this.init();
		}

		try {
			if (this.request.Open) {
				this.request.Open();
			}
			else if (HTML_AJAX.Open) {
				HTML_AJAX.Open(this.request);
			}

			if (this.request.multipart) {
				if (document.all) {
					this.iframe = true;
				} else {
					this.xmlhttp.multipart = true;
				}
			}
	
			var self = this;
			this.xmlhttp.open(this.request.requestType,this.request.completeUrl(),this.request.isAsync);
			if (this.request.customHeaders) {
				for (i in this.request.customHeaders) {
					this.xmlhttp.setRequestHeader(i, this.request.customHeaders[i]);
				}
			}
			if (this.request.customHeaders && !this.request.customHeaders['Content-Type']) {
				var content = this.request.getContentType();
				if(window.opera && content != 'application/xml')
				{
					this.xmlhttp.setRequestHeader('Content-Type','text/plain; charset=utf-8');
					this.xmlhttp.setRequestHeader('x-Content-Type', content + '; charset=utf-8');
				}
				else
				{
					this.xmlhttp.setRequestHeader('Content-Type', content +  '; charset=utf-8');
				}
			}

			if (this.request.isAsync) {
				if (this.request.callback) {
					this.callbackComplete = false;
				}
				this.xmlhttp.onreadystatechange = function() { self._readyStateChangeCallback(); }
			} else {
				this.xmlhttp.onreadystatechange = function() {}
			}
			var payload = this.request.getSerializedPayload();
			if (payload) {
				this.xmlhttp.setRequestHeader('Content-Length', payload.length);
			}
			this.xmlhttp.send(payload);

			if (!this.request.isAsync) {
				if ( this.xmlhttp.status == 200 ) {
					HTML_AJAX.requestComplete(this.request);
					if (this.request.Load) {
						this.request.Load();
					} else if (HTML_AJAX.Load) {
						HTML_AJAX.Load(this.request);
					}
						
					return this._decodeResponse();
				} else {
					var e = new Error('['+this.xmlhttp.status +'] '+this.xmlhttp.statusText);
					e.headers = this.xmlhttp.getAllResponseHeaders();
					this._handleError(e);
				}
			}
			else {
				var self = this;
				this._timeoutId = window.setTimeout(function() { self.abort(true); },this.request.timeout);
			}
		} catch (e) {
			this._handleError(e);
		}
	},
	
	abort: function (automatic) 
	{
		if (this.callInProgress()) {
			this.aborted = true;
			this.xmlhttp.abort();

			if (automatic) {
				HTML_AJAX.requestComplete(this.request);
				this._handleError(new Error('Request Timed Out: time out was '+this.request.timeout+'ms'));
			}
		}
	},

	_readyStateChangeCallback:function() 
	{
		try {
			switch(this.xmlhttp.readyState) {
				case 1:
					break;
				case 2:
					if (this.request.Send) {
						this.request.Send();
					} else if (HTML_AJAX.Send) {
						HTML_AJAX.Send(this.request);
					}
					break;
				case 3:
					if (this.request.Progress) {
						this.request.Progress();
					} else if (HTML_AJAX.Progress ) {
						HTML_AJAX.Progress(this.request);
					}
				break;
				case 4:
					window.clearTimeout(this._timeoutId);
					if (this.aborted) {
						if (this.request.Load) {
							this.request.Load();
						} else if (HTML_AJAX.Load) {
							HTML_AJAX.Load(this.request);
						}
					}
					else if (this.xmlhttp.status == 200) {
						if (this.request.Load) {
							this.request.Load();
						} else if (HTML_AJAX.Load ) {
							HTML_AJAX.Load(this.request);
						}

						var response = this._decodeResponse();

						if (this.request.callback) {
							this.request.callback(response, this.request);
							this.callbackComplete = true;
						}
					}
					else {
						var e = new Error('HTTP Error Making Request: ['+this.xmlhttp.status+'] '+this.xmlhttp.statusText);
						this._handleError(e);
					}
					HTML_AJAX.requestComplete(this.request);
				break;
			}
		} catch (e) {
				this._handleError(e);
		}
	},

	_decodeResponse: function() {
		var content = null;
		try {
			content = this.xmlhttp.getResponseHeader('X-Content-Type');
		} catch(e) {}
		if(!content || content == null)
		{
			content = this.xmlhttp.getResponseHeader('Content-Type');
		}
		if(content.indexOf(';') != -1)
		{
			content = content.substring(0, content.indexOf(';'));
		}
		if(content == 'application/xml')
		{
			return this.xmlhttp.responseXML;
		}
		var unserializer = HTML_AJAX.serializerForEncoding(content);
		return unserializer.unserialize(this.xmlhttp.responseText);
	},

	_handleError: function(e) 
	{
		HTML_AJAX.requestComplete(this.request,e);
		if (this.request.onError) {
			this.request.onError(e);
		} else if (HTML_AJAX.onError) {
			HTML_AJAX.onError(e,this.request);
		}
		else {
			throw e;
		}
	}
}
// Request.js
/**
 * @category	HTML
 * @package	AJAX
 * @author	Joshua Eichorn <josh@bluga.net>
 * @copyright	2005 Joshua Eichorn
 * @license	http://www.opensource.org/licenses/lgpl-license.php  LGPL
 *
 * See Main.js for author/license details
 */
function HTML_AJAX_Request(serializer) {
	this.serializer = serializer;
}
HTML_AJAX_Request.prototype = {

	serializer: null,

	isAsync: false,

	requestType: 'POST',

	requestUrl: '',

	className: null,

	methodName: null,

	timeout: 20000,

	args: null,

	callback: null,

	queue: 'default',

	priority: 0,

	customHeaders: {'X-Requested-With': 'XMLHttpRequest', 'X-Ajax-Engine': 'HTML_AJAX/0.5.2'},

	iframe: false,

	grab: false,

	multipart: false,

	phpCallback: false,

	addArg: function(name, value) 
	{
		if ( !this.args ) {
			this.args = [];
		}
		if (!/[^a-zA-Z_0-9]/.test(name) ) {
			this.args[name] = value;
		} else {
			throw new Error('Invalid parameter name ('+name+')');
		}
	},

	getSerializedPayload: function() {
		return this.serializer.serialize(this.args);
	},

	getContentType: function() {
		return this.serializer.contentType;
	},

	completeUrl: function() {
		if (this.className || this.methodName) {
			this.addGet('c', this.className);
			this.addGet('m', this.methodName);
		}
		if (this.phpCallback) {
			if (HTML_AJAX_Util.getType(this.phpCallback) == 'array') {
				this.phpCallback = this.phpCallback.join('.');
			}
			this.addGet('cb', this.phpCallback);
		}
		if (this.multipart) {
			this.addGet('multipart', '1');
		}
		return this.requestUrl;
	},

	compareTo: function(other) {
		if (this.priority == other.priority) {
			return 0;
		}
		return (this.priority > other.priority ? 1 : -1);
	},

	addGet: function(name, value) {
		var url = new String(this.requestUrl);
		url += (url.indexOf('?') < 0 ? '?' : '&') + escape(name) + '=' + escape(value);
		this.requestUrl = url;
	}
}
// serializer/JSON.js
/*
Copyright (c) 2005 JSON.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

var HTML_AJAX_JSON = {
    copyright: '(c)2005 JSON.org',
    license: 'http://www.crockford.com/JSON/license.html',
    stringify: function (v) {
        var a = [];

        function e(s) {
            a[a.length] = s;
        }

        function g(x) {
            var c, i, l, v;

            switch (typeof x) {
            case 'object':
                if (x) {
                    if (x instanceof Array) {
                        e('[');
                        l = a.length;
                        for (i = 0; i < x.length; i += 1) {
                            v = x[i];
                            if (typeof v != 'undefined' &&
                                    typeof v != 'function') {
                                if (l < a.length) {
                                    e(',');
                                }
                                g(v);
                            }
                        }
                        e(']');
                        return;
                    } else if (typeof x.valueOf == 'function') {
                        e('{');
                        l = a.length;
                        for (i in x) {
                            v = x[i];
                            if (typeof v != 'undefined' &&
                                    typeof v != 'function' &&
                                    (!v || typeof v != 'object' ||
                                        typeof v.valueOf == 'function')) {
                                if (l < a.length) {
                                    e(',');
                                }
                                g(i);
                                e(':');
                                g(v);
                            }
                        }
                        return e('}');
                    }
                }
                e('null');
                return;
            case 'number':
                e(isFinite(x) ? +x : 'null');
                return;
            case 'string':
                l = x.length;
                e('"');
                for (i = 0; i < l; i += 1) {
                    c = x.charAt(i);
                    if (c >= ' ') {
                        if (c == '\\' || c == '"') {
                            e('\\');
                        }
                        e(c);
                    } else {
                        switch (c) {
                        case '\b':
                            e('\\b');
                            break;
                        case '\f':
                            e('\\f');
                            break;
                        case '\n':
                            e('\\n');
                            break;
                        case '\r':
                            e('\\r');
                            break;
                        case '\t':
                            e('\\t');
                            break;
                        default:
                            c = c.charCodeAt();
                            e('\\u00' + Math.floor(c / 16).toString(16) +
                                (c % 16).toString(16));
                        }
                    }
                }
                e('"');
                return;
            case 'boolean':
                e(String(x));
                return;
            default:
                e('null');
                return;
            }
        }
        g(v);
        return a.join('');
    },
    parse: function (text) {
        return 
(/^(\s+|[,:{}\[\]]|"(\\["\\\/bfnrtu]|[^\x00-\x1f"\\]+)*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)+$/.test(text))
 &&
            eval('(' + text + ')');
    }
};
// Loading.js
/**
 * Default loading implementation
 *
 * @category	HTML
 * @package	Ajax
 * @license	http://www.opensource.org/licenses/lgpl-license.php  LGPL
 * @copyright	2005 Joshua Eichorn
 * see Main.js for license Author details
 */
HTML_AJAX.Open = function(request) {
}
HTML_AJAX.Load = function(request) {
}
// util.js
/**
 * Utility methods
 *
 * @category	HTML
 * @package	Ajax
 * @license	http://www.opensource.org/licenses/lgpl-license.php  LGPL
 *
 * See Main.js for author/license details
 */
var HTML_AJAX_Util = {
	registerEvent: function(element, event, handler) 
	{
		element = this.getElement(element);
		if (typeof element.addEventListener != "undefined") {   //Dom2
			element.addEventListener(event, handler, false);
		} else if (typeof element.attachEvent != "undefined") { //IE 5+
			element.attachEvent("on" + event, handler);
		} else {
			if (element["on" + event] != null) {
				var oldHandler = element["on" + event];
				element["on" + event] = function(e) {
					oldHander(e);
					handler(e);
				};
			} else {
				element["on" + event] = handler;
			}
		}
	},
	eventTarget: function(event) 
	{
		if (!event) var event = window.event;
		if (event.target) return event.target; // w3c
		if (event.srcElement) return event.srcElement; // ie 5
	},
	getType: function(inp) 
	{
		var type = typeof inp, match;
		if(type == 'object' && !inp)
		{
			return 'null';
		}
		if (type == "object") {
			if(!inp.constructor)
			{
				return 'object';
			}
			var cons = inp.constructor.toString();
			if (match = cons.match(/(\w+)\(/)) {
				cons = match[1].toLowerCase();
			}
			var types = ["boolean", "number", "string", "array"];
			for (key in types) {
				if (cons == types[key]) {
					type = types[key];
					break;
				}
			}
		}
		return type;
	},
	strRepeat: function(inp, multiplier) {
		var ret = "";
		while (--multiplier > 0) ret += inp;
		return ret;
	},
	encodeUrl: function(input) {
		return encodeURIComponent(input);
	},
	decodeUrl: function(input) {
		return decodeURIComponent(input);
	},
	varDump: function(inp, printFuncs, _indent, _recursionLevel)
	{
		if (!_recursionLevel) _recursionLevel = 0;
		if (!_indent) _indent = 1;
		var tab = this.strRepeat("  ", ++_indent);	
		var type = this.getType(inp), out = type;
		var consrx = /(\w+)\(/;
		consrx.compile();
		if (++_recursionLevel > 6) {
			return tab + inp + "Loop Detected\n";
		}
		switch (type) {
			case "boolean":
			case "number":
				out += "(" + inp.toString() + ")";
				break;
			case "string":
				out += "(" + inp.length + ") \"" + inp + "\"";
				break;
			case "function":
				if (printFuncs) {
					out += inp.toString().replace(/\n/g, "\n" + tab);
				}
				break;
			case "array":
			case "object":
				var atts = "", attc = 0;
				try {
					for (k in inp) {
						atts += tab + "[" + (/\D/.test(k) ? "\"" + k + "\"" : k)
							+ "]=>\n" + tab + this.varDump(inp[k], printFuncs, _indent, _recursionLevel);
						++attc;
					}
				} catch (e) {}
				if (type == "object") {
					var objname, objstr = inp.toString();
					if (objname = objstr.match(/^\[object (\w+)\]$/)) {
						objname = objname[1];
					} else {
						try {
							objname = inp.constructor.toString().match(consrx)[1];
						} catch (e) {
							objname = 'unknown';
						}
					}
					out += "(" + objname + ") ";
				}
				out += "(" + attc + ") {\n" + atts + this.strRepeat("  ", _indent - 1) +"}";
				break;
		}
		return out + "\n";
	},
	quickPrint: function(input,sep) {
		if (!sep) {
			var sep = "\n";
		}
		var type = HTML_AJAX_Util.getType(input);
		switch (type) {
			case 'string':
				return input;
			case 'array':
				var ret = "";
				for(var i = 0; i < input.length; i++) {
					ret += i+':'+input[i]+sep;
				}
				return ret;
			default:
				var ret = "";
				for(var i in input) {
					ret += i+':'+input[i]+sep;
				}
				return ret;
		}
	},
	getAllElements: function(parentElement)
	{
		if( document.all)
		{
			if(!parentElement) {
				var allElements = document.all;
			}
			else
			{
				var allElements = [], rightName = new RegExp( parentElement, 'i' ), i;
				for( i=0; i<document.all.length; i++ ) {
					if( rightName.test( document.all[i].parentElement ) )
					allElements.push( document.all[i] );
				}
			}
			return allElements;
		}
		else
		{
			if (!parentElement) { parentElement = document.body; }
			return parentElement.getElementsByTagName('*');
		}
	},
	getElementsByProperty: function(property, regex, parentElement) {
		var allElements = HTML_AJAX_Util.getAllElements(parentElement);
		var items = [];
		for(var i=0,j=allElements.length; i<j; i++)
		{
			if(regex.test(allElements[i][property]))
			{
				items.push(allElements[i]);
			}
		}
		return items;
	},
	getElementsByClassName: function(className, parentElement) {
		return HTML_AJAX_Util.getElementsByProperty('className',new RegExp('(^| )' + className + '( |$)'),parentElement);
	},
	getElementsById: function(id, parentElement) {
		return HTML_AJAX_Util.getElementsByProperty('id',new RegExp(id),parentElement);
	},
	getElementsByCssSelector: function(selector,parentElement) {
		return cssQuery(selector,parentElement);
	},
	htmlEscape: function(inp) {
		var div = document.createElement('div');
		var text = document.createTextNode(inp);
		div.appendChild(text);
		return div.innerHTML;
	},
	baseURL: function(absolute, filename) {
		var qPos = absolute.indexOf('?');
		if (qPos >= 0) {
			absolute = absolute.substr(0, qPos);
		}
		var slashPos = Math.max(absolute.lastIndexOf('/'), absolute.lastIndexOf('\\'));
		if (slashPos < 0) {
			return absolute;
		}
		return (filename ? absolute.substr(slashPos + 1) : absolute.substr(0, slashPos + 1));
	},
	queryString: function(url) {
		var qPos = url.indexOf('?');
		if (qPos >= 0) {
			return url.substr(qPos+1);
		}
	},
	absoluteURL: function(rel, absolute) {
		if (/^https?:\/\//i.test(rel)) {
			return rel;
		}
		if (!absolute) {
			var bases = document.getElementsByTagName('base');
			for (i in bases) {
				if (bases[i].href) {
					absolute = bases[i].href;
					break;
				}
			}
			if (!absolute) {
				absolute = window.location.href;
			}
		}
		if (rel == '') {
			return absolute;
		}
		if (rel.substr(0, 2) == '//') {
			var slashesPos = absolute.indexOf('//');
			if (slashesPos < 0) {
				return 'http:' + rel;
			}
			return absolute.substr(0, slashesPos) + rel;
		}
		var base = this.baseURL(absolute);
		var absParts = base.substr(0, base.length - 1).split('/');
		var absHost = absParts.slice(0, 3).join('/') + '/';
		if (rel.substr(0, 1) == '/') {
			return absHost + rel;
		}
		if (rel.substr(0, 1) == '.' && rel.substr(1, 1) != '.') {
			return base + rel.substr(1);
		}
		absParts.splice(0, 3);
		var relParts = rel.split('/');
		var loopStart = relParts.length - 1;
		relParts = absParts.concat(relParts);
		for (i = loopStart; i < relParts.length;) {
			if (relParts[i] == '..') {
				if (i == 0) {
					return absolute;
				}
				relParts.splice(i - 1, 2);
				--i;
				continue;
			}
			i++;
		}
		return absHost + relParts.join('/');
	},
	setInnerHTML: function(node, innerHTML, type)
	{
		node = this.getElement(node);

		if (type != 'append') {
			if (type == 'prepend') {
				var oldHtml = node.innerHTML;
			}
			node.innerHTML = '';
		}
		var good_browser = (window.opera || navigator.product == 'Gecko');
		var regex = /^([\s\S]*?)<script([\s\S]*?)>([\s\S]*?)<\/script>([\s\S]*)$/i;
		var regex_src = /src=["'](.*?)["']/i;
		var matches, id, script, output = '', subject = innerHTML;
		var scripts = [];

		while (true) {
			matches = regex.exec(subject);
			if (matches && matches[0]) {
				subject = matches[4];
				id = 'ih_' + Math.round(Math.random()*9999) + '_' + Math.round(Math.random()*9999);

				var startLen = matches[3].length;
				script = matches[3].replace(/document\.write\(([\s\S]*?)\)/ig, 
					'document.getElementById("' + id + '").innerHTML+=$1');

				output += matches[1];
				if (startLen != script.length) {
						output += '<span id="' + id + '"></span>';
				}
				
				output += '<script' + matches[2] + '>' + script + '</script>';
				if (good_browser) {
					continue;
				}
				if (script) {
					scripts.push(script);
				}
				if (regex_src.test(matches[2])) {
					var script_el = document.createElement("SCRIPT");
					var atts_regex = /(\w+)=["'](.*?)["']([\s\S]*)$/;
					var atts = matches[2];
					for (var i = 0; i < 5; i++) { 
						var atts_matches = atts_regex.exec(atts);
						if (atts_matches && atts_matches[0]) {
							script_el.setAttribute(atts_matches[1], atts_matches[2]);
							atts = atts_matches[3];
						} else {
							break;
						}
					}
					scripts.push(script_el);
				}
			} else {
				output += subject;
				break;
			}
		}
		innerHTML = output;

		if (good_browser) {
			var el = document.createElement('span');
			el.innerHTML = innerHTML;

			for(var i = 0; i < el.childNodes.length; i++) {
				node.appendChild(el.childNodes[i].cloneNode(true));
			}
		}
		else {
			node.innerHTML += innerHTML;
		}

		if (oldHtml) {
			node.innerHTML += oldHtml;
		}

		if (!good_browser) {
			for(var i = 0; i < scripts.length; i++) {
				if (HTML_AJAX_Util.getType(scripts[i]) == 'string') {
					scripts[i] = scripts[i].replace(/^\s*<!(\[CDATA\[|--)|((\/\/)?--|\]\])>\s*$/g, '');
					window.eval(scripts[i]);
				}
				else {
					node.appendChild(scripts[i]);
				}
			}
		}
		return;
	},
	classSep: '(^|$| )',
	hasClass: function(o, className) {
		var o = this.getElement(o);
		var regex = new RegExp(this.classSep + className + this.classSep);
		return regex.test(o.className);
	},
	addClass: function(o, className) {
		var o = this.getElement(o);
		if(!this.hasClass(o, className)) {
			o.className += " " + className;
		}
	},
	removeClass: function(o, className) {
		var o = this.getElement(o);
		var regex = new RegExp(this.classSep + className + this.classSep);
		o.className = o.className.replace(regex, " ");
	},
	replaceClass: function(o, oldClass, newClass) {
		var o = this.getElement(o);
		var regex = new RegExp(this.classSep + oldClass + this.classSep);
		o.className = o.className.replace(regex, newClass);
	},
	getElement: function(el) {
		if (typeof el == 'string') {
			return document.getElementById(el);
		}
		return el;
	}
}
