/**
* Classe AJAX
* Classe em JavaScript, para tratar as requisições via AJAX
* Autor: Ricardo Mangabeira, Roberto Rander, David Macedo
* Site: www.randernet.com
* Data de criação: 11/2006
* Versão: 1.4
* Ultima alteracao em: 06/12/2006
*/
function AJAX(){
	/**
	* Artificio utilizado para evitar acesso a variaveis globais com o mesmo
	* nome das locais
	*/
	var self = this;
	/**
	* Variavel local onde ?instanciada o objeto xmlHttpRequest, e que possui os
	* status das requisi?es
	*/
	var req;
	/**
	* Propriedade de Medodo da requisi?o
	*/
	this.metodo;
	/**
	* Propriedade de nome do formulario
	*/
	this.form;
	/**
	* Propriedade com Url responsavel pela requisi?o.
	*/
	this.url;
	/**
	* Propriedade com Id da Tag onde o resultado do AJAX deve ser exibido
	*/
	this.idTag = "";
	/**
	* Propriedade onde ?colocada o retorno do AJAX
	*/
	this.respostaAjax = "";
	/**
	* Propriedade onde ?passada a url, da raiz do servidor
	*/
	this.host = "";
	/**
	* Propriedade onde passamos o nome da fun?o que deve ser chamada
	* apos o retorno da requisi?o ajax, juntamento com o resultado da requisi?o
	*/
	this.funcao = "";
	/**
	* Propriedade que indica qual o tipo de retorno, se texto ou xml
	*/
	this.tipoRespostaAjax = "";
	/**
	* Propriedade que indica qual o texto que aparece enquanto a
	* requisi?o esta sendo feita
	*/
	this.carregandoTexto = "";
	/**
	* Propriedade que indica qual a classe CSS que aparece enquanto a
	* requisi?o esta sendo feita
	*/
	this.carregandoClasseEstilo;
	/**
	* Propriedade boleana, que exibe um alerta com o retorno do AJAX
	*/
	this.debug;
	/**
	* Propriedade que indica qual a imagem que aparece enquanto a
	* requisição esta sendo feita
	*/
	this.icone = {
		carregando: 'imagens/carregando.gif'
	};

	/**
	* Propriedade que indica que deve-se extrair das tags de script as fun?es javascript
	* tipo boleano, true ou false;
	*/
	this.extrairScript;

	/**
	* Propriedade utilizada para recarregar a funcao passada na propriedade de funcao no tempo determinado
	* tipo inteiro em segundos;
	*/
	this.tempo;

	/**
	* Propriedade utilizada para definir o tempo limite de espera do retorno da resposta AJAX
	* tipo inteiro em segundos;
	*/
	this.tempoLimite;
	/**
	* Propriedade codifica os dados para solucionar o problema da acentuação
	*/
	this.codificarDados;
	/**
	* Funcao carregar
	* Funcao que inicializa as principais propriedades e chama a fun?o carregaDocXML
	*/
	this.carregar = function(){
		self.tempo = (self.tempo=="") ? 0 : self.tempo;
		self.respostaAjax = "";
		self.metodo = (self.metodo=="") ? "GET" : self.metodo;
		//Define como padrao Texto
		self.tipoRespostaAjax = (self.tipoRespostaAjax=='')?"texto":self.tipoRespostaAjax; //Texto ou XML
		if (self.idTag!=""){
			_carregando(self.idTag);
		}
		_carregaDocXML();
	};
	/**
	* Fun?o carregaDocXML
	* Fun?o responsavel
	*/
	function _carregaDocXML(){
		req = null;
		// Procura por um objeto nativo (Mozilla/Safari)
		if (window.XMLHttpRequest) {
			req = new XMLHttpRequest();
			// Procura por uma versao ActiveX (IE)
		} else if (window.ActiveXObject) {
			req = new ActiveXObject("Microsoft.XMLHTTP");
		}
		if (req) {
			if(self.metodo=="POST"){
				req.open(self.metodo, self.url, true);
				req.setRequestHeader('Content-Type','application/x-www-form-urlencoded;');
				req.setRequestHeader("Method", "POST "+self.url+" HTTP/1.1");
				var dados = _pegaElementosForm(document.getElementById(self.form));
				req.onreadystatechange = _processReqChange;
				req.send(dados);
			}else{
				req.open(self.metodo, self.url, true);
				req.onreadystatechange = _processReqChange;
				req.send(null);
			}
		}
	};
	/**
	* Função processReqChange - para tratar a comunica?o com o servidor e obter retorno.
	*/
	function _processReqChange(){
		// apenas quando o estado for "completado"
		if (req.readyState == 4) {
			// apenas se o servidor retornar "OK"
			if (req.status == 200) {
				if (self.tipoRespostaAjax == "xml"){
					// retornado como XML, objeto DOM
					this.respostaAjax = req.responseXML;
				}else{
					if(typeof self.codificarDados != "undefined" && self.codificarDados==true){
						resposta = self._urlDecode(req.responseText);  // trata o problema da acentuação codificando os dados 				
					}else{ resposta = req.responseText; }	
					// retornado como texto HTML
					if (self.idTag!=""){
						document.getElementById(self.idTag).innerHTML = resposta;
					}
					this.respostaAjax = resposta;
					self.respostaAjax = resposta;
				}
				/**
				* Extrai o script da pagina requisitada, e adiciona na pagina que originou a requisi?o;
				*/
				if (this.respostaAjax!=="" && self.extrairScript == true)
					_extrairScript(this.respostaAjax);
					
				if (self.debug == true){
					alert(this.respostaAjax);
				}
				
				if (self.funcao!=""){
					if(this.respostaAjax!=""){
						try{
							eval(self.funcao+'('+this.respostaAjax+')');
						}catch(e){};
					}else{
						try{
							eval(self.funcao+'()');
						}catch(e){};
					};

					if (parseInt(self.tempo) > 0){
						_aguardaRetorno(self.tempo);
					}
				};
			} else {
				//limpa o div caso nao tenha resposta
				if (self.idTag!=""){
					document.getElementById(self.idTag).innerHTML = "";
				}
				alert("Houve um problema ao obter os dados:\n" + req.statusText);
			}
		}
	};

	/**
	* Função _pegaElementosForm
	* Parametros:
	* obj = Objeto do formulário
	*/
	function _pegaElementosForm(obj) {
		var elementosFormulario = obj.elements;
		var qtdElementos = elementosFormulario.length;
		var queryString = "";
		var elemento;
	
		//Cria uma funcao interna para concatenar os elementos do form
		this._concatenaElemento = function(nome,valor) { 
					if (queryString.length>0) { 
						queryString += "&";
					}
					if(self.codificarDados==true){
						queryString += self._urlEncode(nome) + "=" + self._urlEncode(valor);
					}else{
						queryString += encodeURIComponent(nome) + "=" + encodeURIComponent(valor);
						//queryString += nome + "=" + valor;
					}
			};	
	
		//Loop para percorrer todos os elementos
		for (var i=0; i<qtdElementos; i++) {
			//Pega o elemento
			elemento = elementosFormulario[i];
			if (!elemento.disabled) {
				//Trabalha com o elemento caso ele nao esteja desabilitado
				switch(elemento.type) {
					//Realiza a acao dependendo do tipo de elemento
					case 'text': case 'password': case 'hidden': case 'textarea': 
						this._concatenaElemento(elemento.name,elemento.value);
						break;
					case 'select-one':
						if (elemento.selectedIndex>=0) {
							this._concatenaElemento(elemento.name,elemento.options[elemento.selectedIndex].value);
						}
						break;
					case 'select-multiple':
						for (var j=0; j<elemento.options.length; j++) {
							if (elemento.options[j].selected) {
								this._concatenaElemento(elemento.name,elemento.options[j].value);
							}
						}
						break;
					case 'checkbox': case 'radio':
						if (elemento.checked) {
							this._concatenaElemento(elemento.name,elemento.value);
						}
						break;
				}
			}
		}
		return queryString;
	};

	/**
	* Função que exibe o carregando para o usuario
	*/
	function _carregando(){
		self.carregandoTexto = (typeof self.carregandoTexto != "undefined")?self.carregandoTexto:'';
		self.carregandoClasseEstilo = (typeof self.carregandoClasseEstilo!= "undefined")?self.carregandoClasseEstilo:'carregandoAJAX';

		var strCarregando = '<div class="'+self.carregandoClasseEstilo+'">';
		strCarregando += (self.carregandoTexto!='')?self.carregandoTexto:'';
		strCarregando += (self.icone.carregando!='')?'<img src="'+self.host+self.icone.carregando+'" />':'';
		strCarregando += '</div>';
		document.getElementById(self.idTag).innerHTML = strCarregando;
	};

	/**
	* Metodo que extrai o script da pagina carregada, e coloca na pagina que faz a requisi?o;
	* possibilitando a execu?o do script
	*/
	function _extrairScript(texto){
   	var ini = 0;
    	if (texto!=""){
    		// loop enquanto achar um script
    		while (ini!=-1){
    			// procura uma tag de script
    			ini = texto.indexOf('<script', ini);
    			// se encontrar
    			if (ini>=0){
    				// define o inicio para depois do fechamento dessa tag
    				ini = texto.indexOf('>', ini) + 1;
    				// procura o final do script
    				fim = texto.indexOf('</script>', ini);
    				// extrai apenas o script
    				codigo = texto.substring(ini,fim);
    				// executa o script
    				novo = document.createElement("script");
    				novo.text = codigo;
    				document.body.appendChild(novo);
    			}
    		}
    	}
	};
	/**
	* url_encode version 1.0 
	* Metodo que codifica os dados que serão postados via AJAX similar ao rawurlencode do PHP
	* Retirado de http://www.phpbrasil.com/articles/print.php/id/1182
	* atualizado em 06-12-2006
	*/
    this._urlEncode =  function(str) { 
        var hex_chars = "0123456789ABCDEF"; 
        var noEncode = /^([a-zA-Z0-9\_\-\.])$/; 
        var n, strCode, hex1, hex2, strEncode = ""; 
        for(n = 0; n < str.length; n++) { 
            if (noEncode.test(str.charAt(n))) { 
                strEncode += str.charAt(n); 
            } else { 
                strCode = str.charCodeAt(n); 
                hex1 = hex_chars.charAt(Math.floor(strCode / 16)); 
                hex2 = hex_chars.charAt(strCode % 16); 
                strEncode += "%" + (hex1 + hex2); 
            } 
        } 
        return strEncode; 
    }; 
	/**
	* url_decode version 1.0 
	* Metodo que decodifica os dados que serão recebidos via AJAX similar ao rawurldecode  do PHP
	* Retirado de http://www.phpbrasil.com/articles/print.php/id/1182
	* atualizado em 06-12-2006
	*/
    this._urlDecode = function(str) { 
        var n, strCode, strDecode = ""; 
        for (n = 0; n < str.length; n++) { 
            if (str.charAt(n) == "%") { 
                strCode = str.charAt(n + 1) + str.charAt(n + 2); 
                strDecode += String.fromCharCode(parseInt(strCode, 16)); 
                n += 2; 
            } else { 
                strDecode += str.charAt(n); 
            } 
        } 
        return strDecode; 
    };  
	/**
	* Metodo para ficar carregando enquanto n? obter o resultado completo do ajax num determinado tempo;
	* Em desenvolvimento
	*/
	function _aguardaRetorno(tempo){
		/*
		tempo = tempo * 1000;
		if (self.respostaAjax!=="" && typeof self.respostaAjax!="undefined"){

		}else{
			setTimeout('+ +',tempo);
		}
		*/
	};


};//fim da classe AJAX



