// JavaScript Document

/*
Clase AJAX
 Creada el 29 de Agosto de 2006;
 Por: LI. Ivan Emilio Andrade Aguilar
 Version 2.0
 Modificada: lunes 9 de noviembre de 2009 17:02:33
*/

/*Cambios de version


2.0
	Inclusion de prototype como parte de la clase para la manupulacion de datos
	reescritura de los modulos principales.
	
	Librerias requeridas
	- Prototype 6.3.+
	- date-es-MX.js (DateJS) 1.+
	
	Ya no se usa un arreglo modificado
	
	ObjetoEnvio(obj) -> Descontinuada
	EnviaAObjeto() -> Descontinuada
	
	Se agrego:
	**Constantes
	_Nuevo
	AJAXCadena
	AJAXEntero
	AJAXFlotante
	AJAXBooleano
	AJAXEntero
	AJAXParametroValor
	AJAXParametroCampo
	AJAXParametroFormulario
	
	**Clases
	(Pendiente)

1.0 > 1.2
* se agrega compatibiliad con objetos, se incluyen 2 metodos y 1 atributo
	AJAXClassCargada ->
	ObjetoEnvio(obj) ->
	EnviaAObjeto() ->

*/

AJAXClassCargada = true;



//Varible Global Para determinar el mensaje de error
var AJAXMensajeDeError = "Su navegador no tiene soporte para visualizar este contenido";
//Metodo a emplearse en el envio de datos
AJAXGet = "GET";
AJAXPost = "POST";

//Estados
AJAXEnvioOk = 4;
AJAXRespuestaOk = 200;
//Manejo de variables de campo
AJAXParametroValor = 0;
AJAXParametroCampo = 1;
AJAXParametroFormulario = 2;
//Variables para el manejo de la informacion
AJAXDespliegaErrores=false;
AJAXClassCargada=true;
//Para pasar las variables que no estan seleccionadas
// se requieren2 valores:
//El usuario decide si se pasan o no
AJAXCamposEnviarTodos = false;
//Si eleigió envia todos los campos cual es el valor por omision
AJAXCamposValorPorOmision = -1;

AJAXCadena = 0;
AJAXEntero = 1;
AJAXFlotante = 2;
AJAXBooleano = 3;
AJAXFecha = 4;

_Nuevo = -1;

AJAXVersionRevision = 2.0;


//Modos de transferencia

AJAXTransURL = 0;
AJAXTransEnt = 1;
AJAXTransCar = 2;


var Obj_Status = {
	'id' : 0,
	'valor' : "",
	'mensaje' : "",
	'_accion' : function(){ return true},
	'initialize' : function(i,v,m){
		this.id = i == null ? 0 : i;
		this.valor = v == null ? 0 : v;
		this.mensaje = m == null ? 0 : m;
	},
	'Accion' : function(a){
		this._accion = a;
	},
	'Activar' : function(){
		this._accion(this.id,this.valor,this.mensaje);
	}
}

var AJAXStatus = Class.create(Obj_Status);

var Obj_HTTPStatus = {
	'_status' : false,
	'initialize': function(){
		this._status = new Array();
		this.Status(_Nuevo,{'id':200, 'valor':'Ok', 'mensaje':'La solicitud se completó satisfactoriamente'});
		this.Status(_Nuevo,{'id':201, 'valor':'Creado', 'mensaje':'Documento creado'});
		this.Status(_Nuevo,{'id':202, 'valor':'Aceptado', 'mensaje':'La solicitud fue aceptada'});
		this.Status(_Nuevo,{'id':203, 'valor':'Información parcial', 'mensaje':'La petición fue aceptada, aun falta completar el documento'});
		this.Status(_Nuevo,{'id':204, 'valor':'Sin respuesta', 'mensaje':'La solicitud no generó algún cambio'});
		this.Status(_Nuevo,{'id':301, 'valor':'El recurso se ha movido', 'mensaje':'El recurso se encuentra disponible en otra URL'});
		this.Status(_Nuevo,{'id':302, 'valor':'Se ha encontrado en URL diferente', 'mensaje':'La informacion se reenviará a otra URL'});
		this.Status(_Nuevo,{'id':303, 'valor':'Método diferente', 'mensaje':'Se sugiere el envio de la informacion por otro método'});
		this.Status(_Nuevo,{'id':304, 'valor':'Sin modificación', 'mensaje':'El contenido no se ha modificado desde la hora y fecha especificada'});
		this.Status(_Nuevo,{'id':400, 'valor':'Mala petición', 'mensaje':'La petición tiene mala sintaxis o no se puede generar respuesta'});
		this.Status(_Nuevo,{'id':401, 'valor':'No autorizado', 'mensaje':'No se envió la cabecera para realizar la autorización'});
		this.Status(_Nuevo,{'id':402, 'valor':'Pago requerido', 'mensaje':'No se envió la cabecera para realizar el pago requerido'});
		this.Status(_Nuevo,{'id':403, 'valor':'Prohibido', 'mensaje':'No se tiene permiso para solicitar petición'});
		this.Status(_Nuevo,{'id':404, 'valor':'No se encontró', 'mensaje':'No se encontró el destino URL no válida'});
		this.Status(_Nuevo,{'id':500, 'valor':'Error interno', 'mensaje':'El servidor encontró un error interno que no permite completar la petición'});
		this.Status(_Nuevo,{'id':501, 'valor':'No implementado', 'mensaje':'EL servidor no cuenta con soporte para el recurso solicitado'});
		this.Status(_Nuevo,{'id':502, 'valor':'Servicio temporalmente sobrecargado', 'mensaje':'No se puede completar la petición actual, demasiadas peticiones'});
		this.Status(_Nuevo,{'id':503, 'valor':'Tiempo de espera agotado', 'mensaje':'El tiempo de espera ha sido excedido y no se ha obtenido respuesta del servidor'});
	},
	'Status' : function(){
		var Parametro = this.Status.arguments;
		var _stRetorno = true;
		switch (Parametro.length){
			case 0: _stRetorno = this._status.length;
					break;
			case 1: _stRetorno = Parametro[0] < this._status.length ? this._status[Parametro[0]] : false;
					break;
			case 2: var _stPos = Parametro[0] == _Nuevo ? this._status.length : Parametro[0];
					var _stObj = Parametro[1];
					var _stId   = _stObj.id ? _stObj.id : 0;
					var _stValor = _stObj.valor ? _stObj.valor: "";
					var _stMensaje = _stObj.mensaje ? _stObj.mensaje : "";
					this._status[_stPos] = new AJAXStatus(_stId,_stValor,_stMensaje);
					break;
		}
		return _stRetorno
	},
	'Obtener' : function (id){
		var _obRetorno = false;
		var _obTotal = this.Status();
		var _ob_i = 0;
		for(_ob_i=0;_ob_i< _obTotal;_ob_i++){
			_obRetorno = this.Status(_ob_i).id == id ? this.Status(_ob_i) : _obRetorno; 
		}
		return _obRetorno;
	}
}

var AJAXHTTPStatus = Class.create(Obj_HTTPStatus);

var Obj_Parametro = {
	'id' : "",
	'valor' : "",
	'initialize' : function(id, val){
		this.id=id;
		this.valor=val;
	},
	'_LimpiaContenido' : function(){
	//Para que viaje apropiadamente la informacion y al momento de recuperar sea lo mas parecido a lo que el usuario escribio originalemnte
	// Se eliminan caracteres como el acento invertido, la direresis fuera de la u el cedil etc.
	// Mismos que serán reemplazados por un espacio en blanco.
	//Para el caso de los caracteres acentuados y la ń y ü se codifican para pasar sin problemas.
	//Se eliminan todos los caracteres no reconocibles
	var _lcSalida = this.valor;
	//Se convierten los caracteres validos no identificados dentro del UTF-8
	_lcSalida = _lcSalida.replace(/@/g,"%2540");
	_lcSalida = _lcSalida.replace(/á/g,"%25E1");
	_lcSalida = _lcSalida.replace(/é/g,"%25E9");
	_lcSalida = _lcSalida.replace(/í/g,"%25ED");
	_lcSalida = _lcSalida.replace(/ó/g,"%25F3");
	_lcSalida = _lcSalida.replace(/ú/g,"%25FA");
	_lcSalida = _lcSalida.replace(/ü/g,"%25FC");
	_lcSalida = _lcSalida.replace(/ń/g,"%25F1");
	_lcSalida = _lcSalida.replace(/Á/g,"%25C1");
	_lcSalida = _lcSalida.replace(/É/g,"%25C9");
	_lcSalida = _lcSalida.replace(/Í/g,"%25CD");
	_lcSalida = _lcSalida.replace(/Ó/g,"%25D3");
	_lcSalida = _lcSalida.replace(/Ú/g,"%25DA");
	_lcSalida = _lcSalida.replace(/Ü/g,"%25DC");
	_lcSalida = _lcSalida.replace(/Ń/g,"%25D1");
	_lcSalida = _lcSalida.replace(/[^a-zA-Z0-9 áéíóúńüÁÉÍÓÚŃÜ@|'*-_+=#%$().,;\n\r\t\/]+/g," ");
	return _lcSalida;
	}
}

var AJAXParametro = Class.create(Obj_Parametro);

var Obj_Funcion = {
	'fn': false,
	'persistir' : false,
	'initialize' : function(fn,pr){
		this.fn = fn;
		this.persistir = pr != null ? pr : false ;
	}
}

var AJAXFuncion =  Class.create(Obj_Funcion);

var Obj_Autenticacion = {
	'Realizar':false,
	'_usuario':"",
	'_contrasena':"",
	'initialize' : function (u,c){
		this._usuario = u;
		this._contrasena = c;
		this.Realizar = u== null && c == null ?false : true;
	}
}

var AJAXAutenticacion = Class.create(Obj_Autenticacion);

var Obj_ProcesaNodo = {
	'DocXML' : false,
	'initialize' : function(xml){
		this.DocXML = xml;
	},
	'Procesa':function(){
		var _prDocXML = this.DocXML;
		var _prTotal = _prDocXML.length;
		return new AJAXNodo(_prDocXML,_prTotal);
	}
};

var AJAXProcesaNodo = Class.create(Obj_ProcesaNodo);

var Obj_Nodo = {
	'DocXML' : false,
	'Total' : 0,
	'initialize' : function(d,t){
		this.DocXML = d;
		this.Total = t;
	},
	'Contenido': function(id,formato){		
		id = id==null ? 0 : id;
		formato = formato == null ? AJAXCadena : formato;
		var _rcpSalida = id<this.Total ? (this.DocXML[id] ? (this.DocXML[id].firstChild ? (this.DocXML[id].firstChild.data ? this.DocXML[id].firstChild.data : "") : "") : "" ) : "";
		switch (formato){
			case AJAXCadena  : _rcpSalida = unescape(_rcpSalida.replace(/%25/g,"%"));
					break;
			case AJAXEntero  : _rcpSalida = Object.isNumber(_rcpSalida) ? parseInt(_rcpSalida) : 0;
					break;
			case AJAXFlotante: _rcpSalida = parseFloat(_rcpSalida);
					break;
			case AJAXBooleano: _rcpSalida = _rcpSalida=="" ? false : _rcpSalida;
					break;
			case AJAXFecha: //Se requiere la libreria DateJS
						_rcpSalida = Date.parseExact(_rcpSalida, "yyyy-MM-dd HH:mm:ss");
					break;
		}
		return _rcpSalida;
	},
	'Atributo' : function(at,id){
		id = id==null ? 0 : id;
		var Retorno = this.DocXML[id].getAttribute(at) ? this.DocXML[id].getAttribute(at) : false;
		return Retorno
	}
};

var AJAXNodo = Class.create(Obj_Nodo);

var Obj_HTTPRequestResultado = {
	'DocXML':false,
	'Texto':false,
	'initialize': function(d,t){
		this.DocXML =  d;
		this.Texto = t;
	}
}

var AJAXHTTPRequestResultado = Class.create(Obj_HTTPRequestResultado);


var Obj_AuxInstanciaParametro = {
	'id' : "",
	'valor' : "",
	'tipo' : AJAXParametroValor,
	'initialize':function(i,v,t){
		this.tipo = t == null ? this.tipo : t;
		this.id = i;
		this.valor = v == null ? "" : v;
	}
}

var AJAXAuxInstanciaParametro = Class.create(Obj_AuxInstanciaParametro);

var Obj_InstanciaParametro = {
	'jxObj': false,
	'initialize':function(jxO){
		this.jxObj = jxO;
	},
	'Valor' : function(id, valor){
		var _vaParametro = new AJAXAuxInstanciaParametro(id,valor);
		this.jxObj.Parametro(_Nuevo,_vaParametro);
	},
	'Campo' : function(id){
		var _vaParametro = new AJAXAuxInstanciaParametro(id,"",AJAXParametroCampo);
		this.jxObj.Parametro(_Nuevo,_vaParametro);
	},
	'Formulario' : function(id){
		var _vaParametro = new AJAXAuxInstanciaParametro(id,"",AJAXParametroFormulario);
		this.jxObj.Parametro(_Nuevo,_vaParametro);
	}
}

var AJAXInstanciaParametro = Class.create(Obj_InstanciaParametro);

var Obj_AJAX = {
	//para compaibilidad de sintaxis de JSON en iExplorer
	'id' : "",
	'_metodo' : AJAXPost,
	'_asincrono' : true,
	'_conexion'  : false,
	'_parametro' : false,
	'_URL'		 : "",
	'_funcion' : false,
	'_autenticacion': false,
	'_TransferenciaEnvia' : AJAXTransURL,
	'_TransferenciaProcesa' : AJAXTransCar,
	'_TransferenciaRecibe' : AJAXTransURL,
	'_HttpRequest' : false,
	'_timeout' : false,
	'_status': false,
	'_fnEj': false,
	'_Estado200' : false,
	'initialize' : function(id,contenedor){
		contenedor =  contenedor;
		this.id = id;
		this._funcion = new Array();
		this._status = new AJAXHTTPStatus();
		this.Reestablecer();
	},
	'Metodo' : function(m){
		this._metodo = m == AJAXGet ? AJAXGet : AJAXPost;
	},
	'URL' : function(u){
		this._URL = u;
	},
	'Reestablecer': function(){
		this._parametro = new Array();
		this._autenticacion = false;
		this._metodo = AJAXPost;
		this._Estado200 = false;
		//this._status = new AJAXHTTPStatus();
		this._autenticacion = new AJAXAutenticacion();
		for(_ree_i = 0 ; _ree_i < this._funcion.length;_ree_i++){
			if(!this._funcion[_ree_i].persistir){
				this._funcion.splice(_ree_i,1);
				_ree_i--;
			}
		}
	},
	'Conectar': function(){
		//Implementacion para codificacion de
		var _coAdcional="";
		var _coEnvio="";
		var _coCadenaParametros = "";
		var _co_i =0;
		this.Parametro(_Nuevo,{'id':"mr" ,'valor':this._TransferenciaEnvia});
		this.Parametro(_Nuevo,{'id':"msp",'valor':this._TransferenciaProcesa});
		this.Parametro(_Nuevo,{'id':"msr",'valor':this._TransferenciaRecibe});
		var _coTotalParametros = this.Parametro();
		//Verifica si se pudo crear el objeto HttpRequest;
		if(this._CreaObjeto()){	//Para cada uno de los parametros
			for(_co_i=0;_co_i< _coTotalParametros;_co_i++){
					// Si no es el primer parametro se asigna & antes de inicluir el parametro
					_coCadenaParametros+= (_co_i>0) ? "&" : "";
					//Se incluye el parametro varible=valor
					// Se emplea el metodo unescape para los valores que se emplean cifrados bajo esta
					// metodo basico
					_coCadenaParametros+= this.Parametro(_co_i);
			}
			// Se codifican la cadena con los valores y variables para enviarse a la URL destino	
			_coCadenaParametros = encodeURI(_coCadenaParametros);
			_coAdicional = (this._metodo==AJAXGet) ? ( this._URL.indexOf("?") > -1 ? "&"+ _coCadenaParametros :"?"+ _coCadenaParametros) : "";
			_coEnvio = (this._metodo==AJAXPost) ? _coCadenaParametros : null;
			//Se abre la peticion de la url, con el metodo POST ys si esta es asincrona
			if (this._autenticacion.Realizar){
				this._HttpRequest.open(this._metodo, this._URL+_coAdicional, this._asincrono, this._autenticacion._usuario, this._autenticacion._contrasena);
			}else{
				this._HttpRequest.open(this._metodo, this._URL+_coAdicional, this._asincrono);
			}
			if(this._metodo==AJAXPost){
				this._HttpRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
			}
			this._HttpRequest.send(_coEnvio);
		}
		else{
			//Alerta de Error de Version de JS
			throw(AJAXMensajeDeError);
		}
	},
	'Parametro' : function(){
		var _paParametro = this.Parametro.arguments;
		var _paResultado = true;
		switch (_paParametro.length){
			case 0: _paResultado = this._parametro.length;
					break;
			case 1: if(_paParametro[0]!=_Nuevo){
						_paResultado = this._parametro[_paParametro[0]].id + "=" + this._parametro[_paParametro[0]]._LimpiaContenido();
					}else{
						_paResultado = new AJAXInstanciaParametro(this);
					}
					break;
			case 2: _paPos = _paParametro[0] == _Nuevo ? this._parametro.length : _paParametro[0];
					_paObj = _paParametro[1];
					_paTipo = _paObj.tipo ? _paObj.tipo : AJAXParametroValor ;
					_paId = _paObj.id ? _paObj.id : "";
					_paValor = _paObj.valor ? _paObj.valor.toString()  : Object.isNumber(_paObj.valor) ? _paObj.valor.toString() : "";
					switch(_paTipo){
						case AJAXParametroValor:
								this._parametro[_paPos]= new AJAXParametro(_paId,_paValor);
							break;
						case AJAXParametroCampo:
								this._RecuperaValor(_paId);
							break;
						case AJAXParametroFormulario:
								this._RecuperaCampos(_paId);
							break;
					}
					break;
		}
		return _paResultado;
	},
	'AlTerminar' : function(fn,persiste){
		persiste = persiste == null ? false : true;
		this._funcion[this._funcion.length] = new AJAXFuncion(fn, persiste);
	},
	'Autenticar' : function(u,p){
		this._autenticar = new AJAXAutenticacion(u,p);
	},
	//Funciones para manipulacion de los resultados
	'Nodo' : function(n,xml){
		var _ndDocXML = xml == null ? this._HttpRequest.responseXML.getElementsByTagName(n) : xml.getElementsByTagName(n);
		var _ndObjNodo = new AJAXProcesaNodo(_ndDocXML);
		return _ndObjNodo.Procesa();
	},
	'Resultado': function(){
		return new AJAXHTTPRequestResultado(this._HttpRequest.responseXML,this._HttpRequest.responseText);
	},
	'Status': function(id){
		return this._status.Obtener(id);
	},
	//Fin de funciones para manipulacion de los resultados
	'_CreaObjeto' : function(){
		this._HttpRequest = false;
		//Plataformas no IE
		if (window.XMLHttpRequest) { // Mozilla, Safari,...
			// Crea el objeto y lo asigna al atibuto del objeto
			this._HttpRequest = new XMLHttpRequest();
			//Verifica si se puede establecer el tipo de respuesta
			if (this._HttpRequest.overrideMimeType) {
				//Establece que la respuesta se manipulara como XML
				this._HttpRequest.overrideMimeType('text/xml');
			}
		 } else if (window.ActiveXObject) { // Plataforma IE
			try {
				//Intenta crear el objeto para Veriiones anteriores a la 6.1
				this._HttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) { //Si no se pudo crear el objeto
				try {
					//intenta crearlo con la libreria para 6.1+
					this._HttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e) {}
			}
		 }
		if(this._HttpRequest) this._HttpRequest.onreadystatechange = this._CambioEstado.bind(this);
		return this._HttpRequest ? true : false
	},
	'_CambioEstado' : function(){
		if(this._HttpRequest.readyState==4){
			this._status.Obtener(this._HttpRequest.status).Activar();
			if(this._HttpRequest.status==200 && !this._Estado200){
				this._Estado200 = true;
				var _ceTotalFunciones = this._funcion.length;
				var _ce_i = 0;
				for(_ce_i = 0;_ce_i < _ceTotalFunciones ;_ce_i++){
					this._fnEj = this._funcion[_ce_i].fn;
					this._fnEj();
				}
			}
		}
	},
	'_RecuperaValor' : function(id){
		var _rvObj = $(id);
		var _rvcampo = "";
		var _rvvalor = "";
		var _rvAgrega = true;
		var i=0;
		switch (_rvObj.tagName.toUpperCase()){
			case "INPUT": switch (_rvObj.getAttribute("type")){
									case "radio": if ($(_rvObj.name).lenght<=1){ 
												  _rvcampo = _rvObj.name;
												  _rvvalor = _rvObj.value;
												  }
												  else{
													 _rvcampo = _rvObj.name;
													 _rvvalor = false;
													  for (i=0;i<$(_rvObj.name).length;i++){
														  	_rvvalor = ($(_rvObj.name)[i].checked) ? $(_rvObj.name)[i].value : _rvvalor; 
														  }
													  }
													  _rvAgrega = valor;
												break;
									case "checkbox":if (_rvObj.checked){ 
														_rvcampo = _rvObj.name;
														_rvvalor = _rvObj.value;
													}else{
														_rvAgrega = false;
													}
												break;
									case  "file": if (AJAXDespliegaErrores){ 
													throw("No hay soporte para envio de archivos a traves de esta versión de AJAXClass\n la variable ["+_rvObj.name+"] no será enviada");
												}
												_rvAgrega= false;
												break;
									default		:_rvcampo = _rvObj.name;
												 _rvvalor = _rvObj.value;
												break;
								}
					break;
			case "SELECT": _rvcampo = _rvObj.name;
						   _rvvalor = _rvObj.value;
					break;
			
			case "TEXTAREA": _rvcampo = _rvObj.name;
							 _rvvalor = _rvObj.value;
					break;
			default: throw( elemento + " no es un Objeto de formulario para procesar");
			
		}
		// Si el campo se puede agrgar
		if(_rvAgrega){
			this._parametro[this._parametro.length]= new AJAXParametro(id,_rvvalor);
		}else{
			//Si el usuario desea enviar los valores por omision.
			if(AJAXCamposEnviarTodos){
				this._parametro[this._parametro.length] = new AJAXParametro(id,AJAXCamposValorPorOmision);
			}
		}
	},
	'_RecuperaCampos' : function(id){
		var _rcFormulario = $(id);
		for(_rc_i=0;_rc_i<_rcFormulario.elements.length;_rc_i++){
			this._RecuperaValor(_rcFormulario.elements[_rc_i].name);
		}
	}
}

var AJAX = Class.create(Obj_AJAX);