/*-------------------------------------------------------------------------------------
'Ajax.js
'Descrição: Funções para manipulação de páginas utilizando o conceito AJAX
'Versão: 1.0.5
'Criado Em: 29/11/2005
'Ultima Atualização: 31/07/2007
'Utilização:
'	- Incluir o .js no html principal
'	- Criar objetivo principal (var MeuAjax = new Ajax();)
'	- Para cada evento, definir (ou não) o loader (MeuAjax.loader(document.window, "Carregando..."))
'	- Para cada evento, executar o script remoto, informando a função de retorno - callback function (MeuAjax.open('GET', 'fillcombo.asp', "ShowRetorno"))
-------------------------------------------------------------------------------------*/

function Ajax(){ 

	// Método para verificar o suporte do browser para uso do AJAX
	// Retorno: True / False
	this.test = function() {
		if(this.init()) {
			return true;
		}
		else {
			return false;
		}
	}

	// Método para inicializar o Ajax de forma cross-browser (de acordo com o browser usado) 
	// Retorno: Objeto para conexão HTTP
	this.init = function() {
		var req;
  		try {req = new ActiveXObject("Microsoft.XMLHTTP");} 
		catch(e) {
			try {req = new ActiveXObject("Msxml2.XMLHTTP");} 
			catch(ex) {
				try {req = new XMLHttpRequest();} 
				catch(exc) {req = null;}
			}
		}
  		return req;
	}

	// Função para interagir com o servidor. 
	// Abre uma conexao Ajax com o argumento pag, e depois envia a resposta para a funcao de callback (cb)
	// Parametros:
	//		-> pag: nome da página a ser executada no servidor
	//		-> cb: função de retorno que será executada (Callback Function)
	//		-> cberror: função de retorno que será executada quando ocorrer erro (Callback Function)
	// Observações:
	//		-> Para ativar a mensagem de carregando, basta setar as propriedades loaderDefObjeto e loaderDefValor do objeto principal
	//			O valor pode ser o objeto, diretamente, ou seu id. Atualmente reconhece: window (status), div (show~hide), select, p e span (altera texto)
	this.open = function(pag, cb, cberror) {
		var resp;

		//Define e iniciliza loader
		var silentMode = this.silentModevar; 
		var loaderDefObjeto = this.loaderDefObjeto; 
		var loaderDefValor = this.loaderDefValor;
		var loaderDefTipo, loaderDefValorOld;
		if (typeof(loaderDefObjeto)=="string") {loaderDefObjeto = document.getElementById(loaderDefObjeto);}

		//Define qual o tipo de loader baseado na tag ou alguma propriedade
		if (typeof(loaderDefObjeto)=="object") {
    		if (loaderDefObjeto.tagName){
    			switch(loaderDefObjeto.tagName){
    				case "P", "SPAN":
    					loaderDefTipo = "changetext";
    					break;
    				case "DIV":
    					loaderDefTipo = "showhide";
    					break;
    				case "SELECT":
    					loaderDefTipo = "changeselect";
    					break;
    			}
    		} else {
				if (loaderDefObjeto.status=="" || loaderDefObjeto.status!="") {loaderDefTipo = "changestatus";}
			}
		}

		function loaderStart(){
			var obj, valor;
			obj = loaderDefObjeto;
			switch (loaderDefTipo){
				case "showhide":
					if (obj) {obj.style.display = "";}
					break;
				case "changestatus":
					if (obj) {loaderDefValorOld = obj.status; obj.status = loaderDefValor;}
					break;
				case "changetext":
					if (obj) {loaderDefValorOld = obj.innerText; obj.innerText = loaderDefValor;}
					break;
				case "changeselect":
					if (obj) {
						loaderDefValor = obj.options[0].text;
						valor = obj.options[0].value;
						obj.options.length=0;
						obj.options.length++;
						obj.options[0].text=loaderDefValor;
						obj.options[0].value=valor;
					}
					break;
			}
		}

		function loaderEnd(){
			var obj;
			obj = loaderDefObjeto;
			if (loaderDefObjeto){
				switch (loaderDefTipo){
					case "showhide":
						if (obj) {obj.style.display = "none";}
						break;
					case "changestatus":
						if (obj) {obj.status = loaderDefValorOld ;}
						break;
					case "changetext":
						if (obj) {obj.innerText = loaderDefValorOld ;}
						break;
					case "changeselect":
						if (obj) {
							obj.options[0].text=loaderDefValor;
						}
						break;
				}
			}
		}

		if(ajax) {

			//Inicializa loader
			loaderStart();

			var sendCont = this.open.arguments[3] ? this.open.arguments[3] : null;
			var Agora = new Date();
			var x, codeA;
			if (pag.indexOf('?')>0)
				pag = pag + "&ts=" + Agora.getTime(); 
			else 
				pag = pag + "?ts=" + Agora.getTime();

			if(sendCont) {
				ajax.open("POST", pag, true);
				ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			} else {
				ajax.open("GET", pag, true);
			}

			ajax.onreadystatechange = function() {
				if(ajax.readyState == 4) {
					if(ajax.status == 200) {
						var resp = ajax.responseText;
						if(!resp) {return false;}
						if (cb) {eval(cb);}

						//Finaliza loader
						loaderEnd();
					} else {
						//Finaliza loader
						loaderEnd();
						if (!silentMode){alert("Não foi possível restaurar informações:\n" + ajax.statusText);}
						if (cberror) {eval(cberror);}					
					}
				}
			}

			// Executa página no servidor
			ajax.send(sendCont);
		}
	}

	// Função que envia os dados de um form para processamento no servidor
	// Parametros:
	//		-> f: nobjeto do form no HTML
	//		-> cb: função de retorno que será executada (Callback Function)
	//		-> cberror: função de retorno que será executada (Callback Function)
	this.send = function(f, cb, cberror) {
		var acao = f.action;
		var metodo = f.method;

		if(!acao) {
			alert("Erro: o valor action do formulario não foi definido");
			return false;
		}
  
		if(!metodo) {
			alert("Erro: o método do formulário não foi definido");
			return false;
		} else
			metodo = metodo.toLowerCase();
  
		var send = new Array();
		var elementos = f.elements;

		for(var i = 0; i < elementos.length; i++) {
			var e = elementos[i];
			if(!e.name)
				continue;
			if(e.disabled)
				continue;
			var nVal = "";
			for(var x = 0; x < e.value.length; x++) {
				codeA = e.value.charCodeAt(x);
				codeA = this.dec2hex(codeA);
				nVal += "%" + codeA;
			}

			var tipo = e.type.toLowerCase();
			if(tipo != "checkbox" && tipo != "radio")
				send[send.length] = e.name + "=" + nVal;
			else if(e.checked)
				send[send.length] = e.name + "=" + nVal;
			}
  
			send = send.join("&");
			if(metodo == "post")
				this.open(acao, cb, cberror, send);
			else
				this.open(acao + "?" + send, cb, cberror);

			return false;
	}
 
	//var loaderDefTipo, loaderDefObjeto, loaderDefValor;
	this.loader = function(objeto, valor) {
		this.loaderDefObjeto = objeto;
		this.loaderDefValor = valor;
	}

	// Função para uso interno da classe, ela converte decimais (entre 0 e 255) em hexadecimal de 2 digitos (ex: A9)
	this.dec2hex = function(dec) {
		var hex_chars = "0123456789ABCDEF";
		var n1 = hex_chars.charAt(Math.floor(dec / 16));
		var n2 = hex_chars.charAt(dec % 16);
  		return n1 + n2;
	}

	this.responseType = function(){return ajax.getResponseHeader("Content-Type");}
	this.responseXML = function(){return ajax.responseXML;}
	this.responseText = function(){return ajax.responseText;}
	this.statusText = function(){return ajax.statusText;}
	this.abort = function(){return ajax.abort();}
	this.getAllResponseHeaders = function(){return ajax.getAllResponseHeaders();}
	this.getResponseHeader = function(item){return ajax.getResponseHeader(item);}
	this.silentMode = function(valor) {this.silentModevar = valor;}
	
	var ajax = this.init();
}