function AJAX(url, callback, data, decoder, sync) {
	this.sync = sync || false;
	this.decoder = decoder || 'plain';

	switch(this.decoder) {
		case 'plain':
		case 'xml':
		case 'json':
			break;
		default:
			this.decoder = 'plain';
	}

	if(window.ActiveXObject)
		this.request = new ActiveXObject('Microsoft.XMLHTTP');
	else
		this.request = new XMLHttpRequest();

	if(this.sync == false) {
		this.request.open('POST', url + '&rand=' + Math.random(), true);

		var a = this;
		this.request.onreadystatechange = function() {
			var r = a.request;
			if(r.readyState == 4) {
				try { a.ontransferend(); } catch(e) {}

				if(r.status == 200) {
					switch(a.decoder) {
						case 'json':
							a.callback(a.parseJSON(r.responseText), a.data);
							break;
						case 'plain':
							a.callback(r.responseText, a.data);
							break;
						case 'xml':
							a.callback(r.responseXML, a.data);
							break;
						default:
							a.callback(null, a.data);
							break;
					}
				}
				else
					a.callback(null, a.data);
			}
		};
	}
	else
		this.request.open('POST', url + '&rand=' + Math.random(), false);

	this.request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

	if(callback)
		this.callback = callback;
	else
		this.callback = this.success;

	this.data = data;

	this.parameter = '';
}

AJAX.prototype.success = function(s, d) {
	alert(s);
}

AJAX.prototype.parseJSON = function(text) {
	if(text.length == 0)
		return null;

	var rex = /[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/
	var reprex = /"(\\.|[^"\\])*"/g

	if(rex.test(text.replace(reprex, '')) == true)
		return null;

	var obj;

	try {
		obj = eval('(' + text + ')');
	}
	catch(e) {
		obj = null;
	}

	return obj;
}

AJAX.prototype.setParameter = function(parameter, value) {
	this.parameter = this.parameter + '&' + encodeURIComponent(parameter) + '=' + encodeURIComponent(value);
}

AJAX.prototype.setForm = function(fid) {
	var f = document.getElementById(fid);
	if(!f)
		return;

	var p = '';

	for(var i = 0; i < f.elements.length; i++) {
		switch(f.elements[i].type) {
			case 'hidden':
			case 'text':
			case 'password':
			case 'textarea':
				p = p + '&' + encodeURIComponent(f.elements[i].name) + '=' + encodeURIComponent(f.elements[i].value);
				break;
			case 'checkbox':
			case 'radio':
				if(f[i].checked)
					p = p + '&' + encodeURIComponent(f.elements[i].name) + '=' + encodeURIComponent(f.elements[i].value);
				break;
			case 'select-one':
				p = p + '&' + encodeURIComponent(f.elements[i].name) + '=' + encodeURIComponent(f.elements[i].value);
				break;
			case 'select-multiple':
				for(var j = 0; j < f.elements[i].options.length; j++) {
					if(f.elements[i].options[j].selected)
						p = p + '&' + encodeURIComponent(f.elements[i].name) + '=' + encodeURIComponent(f.elements[i].options[j].value);
				}
				break;
			case 'button':
			case 'submit':
			case 'reset':
			default:
				break;
		}
	}

	this.parameter = this.parameter + p;
}

AJAX.prototype.send = function() {
	try { this.ontransferstart(); } catch(e) {}

	this.request.send(this.parameter);

	if(this.sync == false)
		return;

	if(this.request.status == 200) {
		try { this.ontransferend(); } catch(e) {}

		var obj = null;
		switch(this.decoder) {
			case 'json':
				obj = this.parseJSON(this.request.responseText);
				break;
			case 'plain':
				obj = this.request.responseText;
				break;
			case 'xml':
				obj = this.request.responseXML;
				break;
			default:
				obj = null;
		}

		return obj;
	}

	try { this.ontransferend(); } catch(e) {}

	return null;
}

AJAX.prototype.ontransferstart = function() {}
AJAX.prototype.ontransferend = function() {}

