Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Henrique Barcelos

Classe AJAX

Recommended Posts

Galera, desenvolvi essa classezinha pra executar a maioria das funções necessárias no uso de AJAX...

 

Essa é a versão BETA ainda, vou melhorando aos poucos, mas ela funciona bem... você só precisa ter um pouquinho de noção de POO se quiser alterar...

 

Edit: Encontrei alguns probleminhas, então corrigi e estou postando a versão BETA2

 

Edit #2: Encontrei outros probleminhas, então corrigi e estou postando a versão BETA3

 

Edit #3: Fiz uma repaginação geral na Classe, mudei alguns métodos, alguns atributos, acho que agora ficou legal xD...

 

Edit #4: Versão 1.0 Final... Acredito que sem maiores bugs. Me avisem se encontrarem algum... http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Edit #5: Versão 2.0 + Documentação liberadas...

 

Baixe os arquivos em:

http://www.megaupload.com/?d=H09ZGZ4L

Achei meio sem sentido criar uma função para fazer o parsing de XML e JSON pq cada documento tem sua própria estrutura, é difícil fazer algo geral...

Apenas adicionei o modo JSON para saber o que você está fazendo (acredite, faz muita diferença)...

 

Se quiser tratar o XML ou o JSON retornados, crie uma função em separado e a passe como parâmetro da propriedade complete, que processa métodos invocados assim que a requisição termina...

 

/** 		
 * 	Nome: myAjax 2.0
 *	Autor: Henrique J. P. Barcelos
 *	Data: 08/11/2009
 
 * 	Este código é livre: você pode redistribuí-lo e/ou modificá-lo
 	sob os termos da GNU General Public License (GPL) como foi publicada pela
 	Free Software Foundation, tanto na versão 3 da Licença, ou
 	(a seu gosto) qualquer versão posterior.

 * 	Este código é distribuido na esperança que ele seja útil,
 	mas SEM QUALQUER GARANTIA.
 
 *	Veja GNU General Public License para mais detalhes.
 	http://www.gnu.org/licenses/gpl.html
 */

var myAjax = function(preferences){
	this.complete = null; //Função ou Array de funções para executar após o carregamento da página
	this.contentLoading = "Carregando..."; //Texto exibido enquanto a página carrega
	this.headers = new Array(); //Headers da requisição HTTP
	this.HTMLObject = null; //objeto HTML que vai receber a resposta da requisição
	this.method = "GET"; //Método da requisição HTTP [GET ou POST]
	this.mode = "TEXT"; //Modo de resposta ['TEXT' = Texto, 'XML' = XML, 'JSON' = JSON]
	this.page = null; //página para a requisição
	this.params = null; //parâmetros passados pela requisição (query string), obrigatório caso o método seja POST
	this.showLoading = true; //Opção de exibir "Carregando" na tela
	this.showResponse = true; //Opção de exibir a resposta no conteúdo do elemento
	this.xmlHttpRequest = null; //variável que vai receber o objeto XMLxmlHttpRequest
	
	//Fazendo as configuracoes
	this.config(preferences);
};

myAjax.prototype = {
	//customização da chamada da função 
	config: function(preferences){
		if (typeof preferences == "object") {
			for (atributo in preferences) {
				if (atributo in this) {
					this["" + atributo.toString() + ""] = preferences[atributo];
				}
			}
		}
	},
	
	//inicialização do objeto XMLxmlHttpRequest
	init: function(){
		//cria o objeto XMLxmlHttpRequest pra Firefox, Chrome, Opera, Safari, etc.
		try {
			this.xmlHttpRequest = new XMLHttpRequest();
		} 
		
		//cria o objeto XMLHttpRequest pra IE 6.0 e posteriormente para IE7+
		catch (e) {
			try {
				this.xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
			} 
			
			catch (e) {
				this.xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
			}
		}
		
	},
	
	//Envia os headers da requisição
	setHeaders: function(){
		if (this.headers != null) {
			for (var i = 0; i < this.headers.length; i++) {
				var header = this.headers[i].header;
				var value = this.headers[i].value;
				this.xmlHttpRequest.setRequestHeader(header, value);
			}
		}
	},
	
	//Faz uma requisição
	load: function(page, element){
		this.init();
		this.page = page;
		
		this.xmlHttpRequest.open(this.method, page, true);
		
		//Se o método for POST, é necessário o header Content-Type, adicionado ao array headers aqui...
		if (this.method == "POST") {
			if (this.params == null) {
				myAjax.handExceptions("config", "Faltam os parâmetros da requisição POST!");
			}
			this.headers.push({
				header: "Content-Type",
				value: "application/x-www-form-urlencoded"
			});
		}
		
		this.setHeaders();
		this.xmlHttpRequest.send(this.params);
		
		if (element) {
			if (typeof element == "string") {
				this.HTMLObject = document.getElementById(element);
			}
			else {
				this.HTMLObject = element;
			}
		}
		else {
			this.showResponse = false;
		}
		
		var obj = this;
		
		this.xmlHttpRequest.onreadystatechange = function(){
			obj.stateChange.call(obj);
		}
	},
	
	//Método chamado quando a requisição muda de estado
	stateChange: function(){
		if (this.xmlHttpRequest.readyState == 4) {
			this.loading(false);
			if (this.xmlHttpRequest.status == 200) {
				if (this.showResponse) {
					this.loadResponse();
				}
				this.callFunctions();
			}
			else {
				myAjax.handExceptions("request", this.xmlHttpRequest.status);
			}
		}
		else {
			if (this.showLoading) this.loading(true);
		}
		
	},
	
	loading: function(opt){
		//Exibe o loading na tela
		if (opt) {
			var tagBody = document.getElementsByTagName("body")[0];
			var divLoading = document.getElementById("myAjaxLoading");
			if (!divLoading) {
				divLoading = document.createElement("div");
				divLoading.setAttribute("id", "myAjaxLoading");
				divLoading.innerHTML = this.contentLoading;
				tagBody.insertBefore(divLoading, tagBody.firstChild);
			}
		}
		//Remove o loading da tela
		else {
			setTimeout(function(){
				var divLoading = document.getElementById("myAjaxLoading");
				if (divLoading) {
					divLoading.parentNode.removeChild(divLoading);
				}
			}, 500);
		}
	},
	
	//Exibe a resposta
	loadResponse: function(){
		var response = null;
		if (this.showResponse) {
			switch (this.mode.toUpperCase()) {
				case "TEXT":
					response = this.getText();
					break;
				case "JSON":
					break;
				case "XML":
					break;
				default:
					myAjax.handExceptions("config", "Modo Inválido! Deve ser \"TEXT\" ou \"XML\"");
			}
			if (response) {
				if (this.HTMLObject) {
					if (this.HTMLObject.nodeName == "INPUT" || this.HTMLObject.nodeName == "OPTION") {
						this.HTMLObject.value = response;
					}
					else {
						this.HTMLObject.innerHTML = response;
					}
				}
				else {
					myAjax.handExceptions("DOM", "Elemento inválido ou inexistente!");
				}
			}
		}
	},
	
	//Faz a chamada das funções quando a requisição for completada
	callFunctions: function(){
		var complete = this.complete;
		if (complete != null) {
			if (typeof complete == "object") {
				for (var i = 0; i < complete.length; i++) {
					if (typeof complete[i] == "function") {
						complete[i].call(this);
					}
					else {
						myAjax.handExceptions("DOM", "Função Inválida!");
					}
				}
			}
			else if (typeof complete == "function") {
				complete.call(this);
			}
			else {
				myAjax.handExceptions("DOM", "Função inválida ou inexistente!");
			}
		}
	},
	
	getXML: function(){
		return this.xmlHttpRequest.responseXML;
	},
	
	getText: function(){
		return this.xmlHttpRequest.responseText;
	},
	
	abort: function(){
		this.xmlHttpRequest.abort();
		return false;
	}
};

//Tratamento de Exceções
//Obs.: Não quero que este método seja acessado fora da classe, então eu o declaro como privado (fora do prototype)
myAjax.handExceptions = function(type, error){
	if (type == undefined) type = "request";
	if (error == undefined) error = "Erro desconhecido!";
	
	switch (type) {
		case "request":
			switch (error) {
				case 400:
					throw new Error("Erro #400: Bad Request!");
					break;
				case 403:
					throw new Error("Erro #403: Acesso proibido!");
					break;
				case 404:
					throw new Error("Erro #404: Arquivo não encontrado!");
					break;
				case 408:
					throw new Error("Erro #408: Atingiu o tempo limite de conexão!");
					break;
				case 500:
					throw new Error("Erro #500: Internal Server new Error!");
					break;
				case 504:
					throw new Error("Erro #504: Gateway offline!");
					break;
				default:
					throw new Error("Erro de requisição desconhecido!");
					break;
			}
			break;
			
		case "DOM":
			throw new Error("Erro DOM: " + error);
			break;
			
		case "config":
			throw new Error("Error de configuração: " + error);
			break;
			
		default:
			throw new Error("Erro desconhecido!");
	}
}

Usando:

 

Requisição GET comum:

elemento.onclick = function(){
 var ajax = new myAjax();
 ajax.load("pagina.php", "ID do elemento que receberá a resposta");
}

 

Requisição GET com função executando ao fim do carregamento:

elemento.onclick = function(){
 var ajax = new myAjax({
 complete: function(){
 alert("Funciona!!! :D");
 }
 });
 ajax.load("pagina.php", "ID do elemento que receberá a resposta");
}

ou

 

elemento.onclick = function(){
 var ajax = new myAjax({
 complete: funcao //nome da função sem parênteses...
});
 ajax.load("pagina.php", "ID do elemento que receberá a resposta");
}

ou

 

elemento.onclick = function(){
 var ajax = new myAjax({
 complete: [funcao1, funcao2, funcao3] //array de funções, também com o nome da função sem parênteses...
});
 ajax.load("pagina.php", "ID do elemento que receberá a resposta");
 }

 

 

Requisição POST:

elemento.onclick = function(){
 var ajax = new myAjax({
 method: "POST",
 params: "var1=teste&var2=teste"
 });
 ajax.load("pagina.php", "ID do elemento que receberá a resposta");
}

 

Se não quiser mostrar diretamente a resposta da requisição:

elemento.onclick = function(){
 var ajax = new myAjax({
 method: "POST",
 params: "var1=teste&var2=teste",
 showResponse: false //opicional... Na versão 1.0, basta apenas omitir o segundo parâmetro do método load abaixo...
 });
 ajax.load("pagina.php");
 }

 

Manipulando o retorno da requisição:

elemento.onclick = function(){
 var ajax = new myAjax({
 method: "POST",
 params: "var1=teste&var2=teste",
 showResponse: false,
 complete: function(){
 var respota = this.getText(); //retorna o valor da resposta enviada pela requisição...
 if(resposta == algum_valor){
 funcao1();
 } else {
 funcao2();
 }
 }
 });
 ajax.load("pagina.php");
 }

Ajax dentro de Ajax:

elemento.onclick = function(){
 var ajax = new myAjax({
 complete: function(){
 var ajax2 = new myAjax();
 ajax2.load("pagina2.php", "content");
 }
 });
 ajax.load("pagina.php", "ID do elemento que receberá a resposta");
}

Personalizando a mensagem de loading:

elemento.onclick = function(){
 var ajax = new myAjax({
 contentLoading: "<img src='loading.gif' alt='Carregando...'/>"
 });
 ajax.load("pagina.php", "ID do elemento que receberá a resposta");
}

Simples não??? http://forum.imasters.com.br/public/style_emoticons/default/graduated.gif

Compartilhar este post


Link para o post
Compartilhar em outros sites

show de bola!

 

Podia só deixar o MODO mais intuitivo.

Outra coisa, seria interessante usar os nomes dos metodos e atributos em inglês, pra estrangeiros poderem usar também ;)

 

Mais uma coisa hehe.

Em vez de pensar no XML, ou talvez além do XML, use JSON, XML está ficando ultrapassado e JSON está começando a tomar o lugar dele, se é que já não tomou.

A função eval() faz milagres com o JSON.

 

Abraços

Compartilhar este post


Link para o post
Compartilhar em outros sites

A maioria dos navegadores atuais ainda não suporta JSON nativamente, mas ele é tratado com texto, ou seja, pode ser pego com o método getText();<br><br>Quanto à nomenclatura em inglês, que se explodam os estrangeiros... Eu tenho que me virar pra entender artigos em inglês, pq eles não podem aprender Português?<br><br>A função eval é um pouco perigosa, tem que ter muito cuidado ao usar...<br>

Compartilhar este post


Link para o post
Compartilhar em outros sites

var a = "{a: 'a', b: 'b'}";

var o = eval( '(' + a + ')' );

alert(o.a);

 

qual o perigo?

Leiam:

http://www.milfont.org/tech/2007/10/02/eval-is-evil/

 

Em breve vou postar a versão atualizada com parsing de XML e JSON...

 

Ahh, e JSON é texto mesmo, uai!

O Firefox 3.5 já tem suporte nativo à JSON...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fiz algumas pequenas correções no mecanismo de execução de funções, breve farei uma repaginação geral, tá meio feinha xD...

 

Fiz o update: Versão RC1 tá aih ^^/

 

Edit: Versão 1.0 liberada...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.