/**

	Título..: VeryTinyAJAX 0.5, Wrapper JavaScript simple a funciones XMLHTTP para AJAX
  Licencia: GPL (http://www.gnu.org/licenses/gpl.txt)
	Autores.: Pablo Rodríguez Rey (mr.xkr -en- inertinc -punto- org)
	          http://mr.xkr.inertinc.org/
            Javier Gil Motos (cucaracha -en- inertinc -punto- org)
            http://cucaracha.inertinc.org/

	Agradecimientos a Cucaracha, por darme interés en el desarrollo de webs usando
	AJAX y proveerme del ejemplo básico con el que está desarrollada esta librería.
	También a Binny V A (binnyva -en- hotmail -punto- com
	http://www.geocities.com/binnyva) por la función adump.

*/


// declarar el objeto XML-HTTP global
var http;

// constante de versión de protocolo de transacción
var httpTP="VeryTinyAJAX/tp1:";

// constantes para httpRequest
var hGET=0;
var hPOST=1;

// funciones auxiliares generales
function gid(id) { return(document.getElementById(id)); }

// parsear cadena para ser enviada por GET/POST
function gescape(torg) {
	var d=""+torg;
	try { var d=d.replace(/\"/gi,"%22"); } catch(e) {}
	try { var d=d.replace(/\\/gi,"%5C"); } catch(e) {}
	try { var d=d.replace(/\?/gi,"%3F"); } catch(e) {}
	try { var d=d.replace(/&/gi,"%26"); } catch(e) {}
	try { var d=d.replace(/\+/gi,"%2B"); } catch(e) {}
	try { var d=d.replace(/ /gi,"+"); } catch(e) {}
	return(d);
}

// información de versión
function httpVersion() { return("VeryTinyAJAX/0.4b"); }

// crea el objeto XML-HTTP
function httpObject() {
	var xmlhttp;
	// comprobar que el navegador soporta XMLHttpRequest
	try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
	catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
	catch (e) { try { xmlhttp = new XMLHttpRequest(); }
	catch (e) { xmlhttp = false; } } }
	return(xmlhttp);
}

// estado de la petición
function httpState() {
	try { return(http.readyState); }
	catch (e) { return(5); }
}

// cadena de estado de la petición
function httpStateString() {
	try { var rs=http.readyState; }
	catch (e) { var rs=5; }
	switch (rs) {
	case 0: return("Uninitialized")
	case 1: return("Loading");
	case 2: return("Loaded");
	case 3: return("Interactive");
	case 4: return("Complete");
	case 5: return("Server Crashed");
	}
}

// Indicar si se ha completado la operación
function httpComplete() {
	if (http.readyState==4) return(true);
	else return(false);
}

// Devolver los datos recibidos
function httpData() {
	return(http.responseText);
}

// Devolver los datos recibidos en formato documento XML
function httpXML() {
	return(http.responseXML);
}

// Devolver el estado del servidor
// Si se detecta error, el servidor no estará disponible
function httpStatus() {
	try { return(http.status); }
	catch(e) { return(0); }
}

// Comprobar que la respuesta del servidor es la 200 (HTTP OK)
function httpError() {
	if (http.readyState==4) {
		try { var ok=(http.status!=200); }
		catch(e) { return(true); }
		return(ok);
	}
}

// Muestra un mensaje de error dependiendo del tipo de error encontrado
function httpErrorShow() {
	if (httpError()) {
		if (httpStatus()) alert("Se ha encontrado el error "+httpStatus()+" en el servidor.");
		else alert("El servidor no responde a la petición!\nPruebe dentro de unos instantes.");
	}
}

// Realizar un envío de datos http
function httpSend(method, url, data, eventfunction) {
	var sdata=(data?data:"");
	var async=(eventfunction?true:false);
	http=httpObject();
	switch (method) {
	case hGET: http.open("GET",url+"?"+sdata,async); sdata=null; break;
	case hPOST: http.open("POST",url,async); break;
	default: return(false);
	}
	if (async) http.onreadystatechange=eventfunction;
	http.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=ISO-8859-1"');
	http.send(sdata);
	return(true);
}

// Devuelve todos los campos y datos
// de un formulario en forma campo1=dato1&campo2=dato2&...
function httpFormFields(formObject) {
	var fields="";
	for (i=0;i<formObject.length;i++) {
		if (!formObject[i].name) continue;
		if (formObject[i].type=="radio" && !formObject[i].checked) continue;
		fields+=(i>0?"&":"")+formObject[i].name+"="+gescape(httpGetObjectValue(formObject[i]));
	}
	return(fields);
}

// Habilitar o deshabilitar la posibilidad de introducción
// o modificación de datos de un formulario completo.
function httpFormFieldsEnabled(formObject,isEnabled) {
	for (x=0;x<formObject.length;x++) {
		try { formObject[x].disabled=!isEnabled; }
		catch(e) {}
	}
}

// Devuelve todos los campos y datos de un lista de identificadores
// tipo id1,id2,id3 en forma id1=dato1&id2=dato2&...
function httpGetFields(fieldNames) {
	var fn=fieldNames.split(",");
	var fields="";
	var formObject;
	for (i=0;i<fn.length;i++) {
		formObject=gid(fn[i]);
		if (!formObject) continue;
		if (formObject.type=="radio" && !formObject.checked) continue;
		fields+=(i>0?"&":"")+fn[i]+"="+gescape(httpGetObjectValue(formObject));
	}
	return(fields);
}

// Devuelve un valor de un campo
function httpGetObjectValue(formObject) {
	switch (formObject.type) {
	case "checkbox": return(formObject.checked?"1":"0");
	case "radio": case "button": case "select-one": case "text": case "textarea": default: return(formObject.value);
	}
}

// devuelve un objeto con las variables creadas con la función aput
function aget(fullData) {
	var d=(fullData==null?httpData():fullData);
	var o=new Object();
	var n=0;
	var p0,p1,p2,isa;
	var debug=false;
	// comprobar si usa una transacción
	if (d.substring(0,httpTP.length)!=httpTP) debug=true;
	else d=d.substring(httpTP.length);
	// leer datos
	while (true) {
		try {
			p0=d.indexOf("="); if (!p0) break;
			p1=d.indexOf("("); if (!p1) break;
			p2=d.indexOf(")"); if (!p2) break;
			isa=d.substring(p2+1,p2+2); if (!isa) break;
			isa=(isa=="$"?true:false);
			name=d.substring(0,p1); if (!name) { alert("aget warning: bad output"+"\n\n"+httpData()); break; }
			plength=parseInt(d.substring(p1+1,p2));
			data=d.substring(p0+1,p0+plength+1);
			if (!isa) eval("o."+name+"=data;");
			else eval("o."+name+"="+data+";");
			d=d.substring(p0+plength+2);
		} catch(e) {
			if (debug) alert("aget error: "+e+"\n\n"+httpData());
			return(false);
		}
	}
	return(o);
}

// mensaje de error en aget predefinido
function agetErrorShow() {
	alert("Error en procesamiento. Salida devuelta:\n\n"+httpData());
}

// Función auxiliar para crear cadenas PHP sin caracteres de control
function aescape(torg) {
	var d=""+torg;
	try { var d=d.replace(/\\/gi,"\\\\"); } catch(e) {}
	try { var d=d.replace(/\"/gi,"\\\""); } catch(e) {}
	try { var d=d.replace(/\'/gi,"\\'"); } catch(e) {}
	try { var d=d.replace(/\n/gi,"\\n"); } catch(e) {}
	try { var d=d.replace(/\t/gi,"\\t"); } catch(e) {}
	try { var d=d.replace(/\f/gi,"\\f"); } catch(e) {}
	try { var d=d.replace(/\r/gi,"\\r"); } catch(e) {}
	return(d);
}

// Devuelve un cadena con el objeto serializado a PHP
// ATENCIÓN: Debe ser saneado por la función verifyArray(cadena)
//           para evitar inyecciones de código a PHP.
function aput(data,level,human_readable) {
	var i,j,k,n=(level?level:0),r="",s="";
	if (human_readable) { s="\n"; for (i=0;i<n;i++) s+="\t"; }
	if (data==null) return("null");
	if (typeof data=="object") {
		if (data.constructor.toString().indexOf("Array")!=-1) {
			j=0;
			r+=s+"Array(";
			for (i in data) {
				if (typeof data[i]!="function") {
					if (j) r+=s+","; j++;
					r+=aput(data[i],n+1,human_readable);
				}
			}
			r+=s+")";
		} else {
			k=0;
			for (i in data) {
				k++;
				if (k>1) {
					r+=s+'Array(';
					break;
				}
			}
			j=0;
			for (i in data) {
				if (typeof data[i]!="function") {
					if (j) r+=","; j++;
					r+=s+'"'+i+'"=>'+aput(data[i]);
				}
			}
			if (k>1) r+=s+')';
		}
	} else {
		r+=(typeof data=="number"?data:'"'+aescape(data)+'"');
	}
	return(r);
}

// volcar el árbol de una variable JavaScript
function adump(arr,level) {
	var dumped_text="";
	if (!level) level=0;

	// the padding given at the beginning of the line
	var level_padding="";
	for (var j=0;j<level;j++) level_padding+="\t";

	if (typeof(arr)=='object') { // Array/Hashes/Objects
		for (var item in arr) {
			var value=arr[item];
			if (typeof(value)=='object') { // if it is an array
				var size=0; for (var none in value) size++;
				dumped_text+=level_padding+'["' + item + '"] ('+size+') =>\n';
				dumped_text+=adump(value,level+1);
			} else {
				dumped_text+=level_padding+'["' + item + '"] => '+typeof(value)+'("' + value + '")\n';
			}
		}
	} else { // Strings/Chars/Numbers etc.
		dumped_text="("+typeof(arr)+") "+arr;
	}
	return dumped_text;
}
