function npAjax(done, fail, eval_res) {
	newAjax = this;
	this.data = new Array();
	this.onDone = done;
	this.onFail = fail;
	this.onDoneText = false;
	this.onFailText = false;
	this.transport = this.getTransport();
	this.transport.onreadystatechange = ajaxTrampoline(this);
	this.eval_res = eval_res;
}

npAjax.prototype.npParse = function (text) {
		
}

npAjax.prototype.get = function (uri, query, force_sync) {
	// Firefox doesn't call onDone and onFail handlers if you force_sync
	force_sync = force_sync || false;
	
	if( typeof query == 'array' )
		query = ajaxArrayToQueryString(query);
	
	fullURI = uri+(query ? ('?'+query) : '');
	this.transport.open('GET', fullURI, !force_sync );
	this.transport.send('');
}

npAjax.prototype.post = function (uri, data, force_sync) {
	force_sync = force_sync || false;
	if( typeof data == 'object' )
		data = ajaxArrayToQueryString(data);
		
	this.transport.open('POST', uri, !force_sync);
	this.transport.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	this.transport.send(data);
}

npAjax.prototype.saveData = function () {
	if( typeof arguments[0] == 'object' )
		arguments = arguments[0];
	
	var id = arguments[0];
	this.data[id] = new Array();
	
	element = 0;
	for(i=1; i<arguments.length; i++) {
		d = arguments[i];
		compare = d.split('=');
		idway = compare[1].split('.');
		
		this.data[id][element] = new Array();
		this.data[id][element]['id'] = idway[0];
		this.data[id][element]['value'] = eval('gete(idway[0]).'+idway[1]);
		this.data[id][element]['property'] = idway[1];
		this.data[id][element]['name'] = compare[0];
		
		element++;
	}
	this.data[id]['ajax'] = gete('ajax'+id).innerHTML;	
}

npAjax.prototype.restoreData = function (id) {
	gete('ajax'+id).innerHTML = this.data[id]['ajax'];
	for(i=0; i<this.data[id].length; i++) {
		obj = gete(this.data[id][i]['id']);
		eval('obj.'+this.data[id][i]['property']+' = \''+this.data[id][i]['value']+'\'');	
	}
}

npAjax.prototype.data2str = function (id) {
	var arr = new Array;
	for(i=0; i<this.data[id].length; i++)
		arr[this.data[id][i]['name']] = this.data[id][i]['value'];
	return arr;
}

npAjax.prototype.stateDispatch = function ()
{
	if( this.transport.readyState == 1 && this.showLoad )
		ajaxShowLoadIndicator();
  
	if( this.transport.readyState == 4 ) {
		if( this.showLoad )
			ajaxHideLoadIndicator();
			
		if( this.transport.status >= 200 && this.transport.status < 300) {
			if( this.eval_res ) this.parseResponse();
			if( this.onDone ) this.onDone(this, this.transport.responseText);
		} else {
			if( this.onFail ) this.onFail(this, this.transport.responseText);
		}
	}
}

npAjax.prototype.getTransport = function () {
	var ajax = null;
	
	try { ajax = new XMLHttpRequest(); }
	catch(e) { ajax = null; }
	
	try { if(!ajax) ajax = new ActiveXObject("Msxml2.XMLHTTP"); }
	catch(e) { ajax = null; }
	
	try { if(!ajax) ajax = new ActiveXObject("Microsoft.XMLHTTP"); }
	catch(e) { ajax = null; }
	
	return ajax;
}

npAjax.prototype.collect = function (arr, func) {
	var n = [];
	for(var i = 0; i < arr.length; i++) {
		var v = func(arr[i]);
		if (v != null) n.push(v);
	}
	return n;
}

npAjax.prototype.serialize = function (form) {
	var result = new Array();
	var g = function(n) {
		return form.getElementsByTagName(n)
	};
	var nv = function(e){
		if (e.name) result[e.name] = e.value;
	};
	this.collect(g('input'), function(i) {
		if ((i.type != 'radio' && i.type != 'checkbox') || i.checked) return nv(i);
	});
	
	this.collect(g('select'), nv);
	this.collect(g('textarea'), nv);
	return result;
}

npAjax.prototype.serializeById = function (form) {
	var result = new Array();
	var g = function(n) {
		return form.getElementsByTagName(n)
	};
	var nv = function(e){
		if (e.id) result[e.id] = e.value;
	};
	this.collect(g('input'), function(i) {
		if ((i.type != 'radio' && i.type != 'checkbox') || i.checked) return nv(i);
	});
	
	this.collect(g('select'), nv);
	this.collect(g('textarea'), nv);
	return result;
}


npAjax.prototype.parseResponse = function() {
	if(!this.transport || !this.transport.responseText)
		return;
		
	var response = this.transport.responseText.replace(/^[\s\n]+/g, '');
	
	if(response.substr(0,10)=="<noscript>") {
		try {
			var arr = response.substr(10).split("</noscript>");
			eval(arr[0]);
			this.transport.responseText = arr[1];
		} catch(e) {
		}
	}
}

function ajaxTrampoline(ajaxObject) {
  return function () { ajaxObject.stateDispatch(); };
}

function ajaxArrayToQueryString(queryArray) {
	var sep = '';
	var query = "";
	
	for( var key in queryArray ) {
		//query = query+sep+key+'='+queryArray[key];
		query = query+sep+encodeURIComponent(key)+'='+encodeURIComponent(queryArray[key]);
		sep = '&';
	}
	return query;
}

function ajaxArrayToFormData(queryArray) {
	for( var key in queryArray ) {
		alert('key = "'+key+'"; value = "'+queryArray[key]+'"');
		gete(key).value = queryArray[key];
	}
}

var ajaxLoadIndicatorRefCount = 0;

function ajaxShowLoadIndicator() {
	indicatorDiv = ge('ajaxLoadIndicator');
	if( !indicatorDiv ) {
		indicatorDiv = document.createElement("div");
		indicatorDiv.id = 'ajaxLoadIndicator';
		indicatorDiv.innerHTML = 'Loading';
		indicatorDiv.className = 'ajaxLoadIndicator';
		document.body.appendChild(indicatorDiv);
	}
  
	indicatorDiv.style.top = (5 + pageScrollY()) + 'px';
	indicatorDiv.style.left = (5 + pageScrollX()) + 'px';
	indicatorDiv.style.display = 'block';
	ajaxLoadIndicatorRefCount++;
}

function ajaxHideLoadIndicator() {
	ajaxLoadIndicatorRefCount--;
	if( ajaxLoadIndicatorRefCount == 0 )
		ge('ajaxLoadIndicator').style.display = '';
}

