function Ajax()
{
	
	/*************************
	 *** PROPERTIES
	 ************************/
	xmlhttp = undefined;
	fila    = [];
	ifila   = 0;
	method  = "GET";
	sync    = true;
	loadmsg = "Carregando...";
	flagloadmsg = false;
	
	/*************************
	 *** METHODS ALIASES
	 ************************/
	this.Ajax = Ajax;
	this.startAjax = startAjax;
	this.putInPlace = putInPlace;
	this.requestGetFor = requestGetFor;
	this.requestGetBy = requestGetBy;
	this.requestFormPostFor = requestFormPostFor;
	this.requestFormPostBy = requestFormPostBy;
	this.requestFieldPostFor = requestFieldPostFor;
	this.requestFieldPostBy = requestFieldPostBy;
	this.check = check;
	this.run = run;
	this.receive = receive;
	this.setSync = setSync;
	this.fetchForm = fetchForm;
	this.setLoadMsg = setLoadMsg;
	
	/*************************
	 *** CONSTRUCTOR
	 ************************/
	Ajax();
	
	/*************************
	 *** METHODS DEFINITION
	 ************************/

	function Ajax()
	{
		startAjax();
	}

	function setSync(arg)
	{
		sync = arg;
	}

	function setLoadMsg(msg)
	{
		flagloadmsg = true;
		if(msg != undefined)
			loadmsg = msg;
	}

	function startAjax()
	{
		 if (window.ActiveXObject) {
		      var objectNames = [
		                      "Msxml2.XMLHTTP.5.0", 
		                      "Msxml2.XMLHTTP.4.0", 
		                      "MSXML2.XMLHTTP.3.0", 
		                      "MSXML2.XMLHTTP", 
		                      "Microsoft.XMLHTTP"
		      ];
		      for(var i=0; i < objectNames.length; i++) {
		              try {
		                      xmlhttp = new ActiveXObject(objectNames[i]);
		              } catch(e) {
		              }
		      }
		}
		
		if (! xmlhttp && window.XMLHttpRequest) {
		      try {
		              xmlhttp = new XMLHttpRequest();
		      } catch(e) {
		      }
		}
		
		if (! xmlhttp) {
		      alert("Seu browser não esta preparado para o ajax");
		}

		/*
		try{
			xmlhttp = new XMLHttpRequest();
		}catch(e){//ee
			try{
				xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
			}catch(e){
				try{
					xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
				}catch(e){//E
					xmlhttp = false;
				}
			}
		}
		*/
	}
	
	function requestGetFor(url, id)
	{
		//Adiciona à fila	
		fila[fila.length] = {"id" : id,"url" : url, "func" : "putInPlace", "method":"GET", "send":null};
		check();
	}
	
	function requestGetBy(url, func)
	{			
		//Adiciona à fila
		fila[fila.length] = {"url":url, "func":func, "method":"GET", "send":null};
		check();
	}
	
	function requestFormPostFor(url, form_name, id)
	{
		//Adiciona à fila
		fila[fila.length] = {"url":url, "id":id, "func":"putInPlace", "method":"POST", "send":fetchForm(form_name)};
		check();
	}

	function requestFormPostBy(url, form_name, func)
	{
		//Adiciona à fila
		fila[fila.length] = {"url":url, "func":func, "method":"POST", "send":fetchForm(form_name)};
		check();
	}

	function requestFieldPostFor(url, field, id)
	{
		//Adiciona à fila
		fila[fila.length] = {"url":url, "id":id, "func":"putInPlace", "method":"POST", "send":field};
		check();
	}

	function requestFieldPostBy(url, field, func)
	{
		//Adiciona à fila
		fila[fila.length] = {"url":url, "func":func, "method":"POST", "send":field};
		check();
	}
	
	function check()
	{
		//Se não há conexões pendentes, executa
		//alert(ifila+1 + " == "+ fila.length);
		if(ifila+1 == fila.length) run();
	}

	function putInPlace(cont)
	{
		obj = document.getElementById(fila[ifila]["id"]);
		obj.innerHTML = cont;
		return true;
	}

	function fetchForm(form_name)
	{
		temp = "";
		size = document.forms[form_name].elements.length;
		for(i = 0; i < size; i++) {
			if(temp.length) temp += "&";
			input = document.forms[form_name].elements[i];
			switch(input.type) {
				case "checkbox":
				case "radio":
					if(input.checked)
						temp += input.name + "=" + input.value; 
				break;

				default: 
				temp += input.name + "=" + input.value; 
					
			}
		}
		return temp;
	}

	function run()
	{
		//alert("run() = ifila: " + ifila + " : fila[ifila][\"url\"]:" + fila[ifila]["url"] + " : fila[ifila][\"func\"]" + fila[ifila]["func"]);
		//Carregando...
		if(fila[ifila]["func"] == "putInPlace" && flagloadmsg){
			putInPlace("<span class='carregando'>" + loadmsg + "</span>");
		}
		//Abre a conexão
		xmlhttp.open(fila[ifila]["method"], fila[ifila]["url"], sync);
		//Executa
		if(fila[ifila]["method"] == "POST") {
			xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		}
		//alert(fila[ifila]["send"]);
		xmlhttp.send(fila[ifila]["send"]);
		//Função para tratamento do retorno
		xmlhttp.onreadystatechange = receive;
	}
	
	function receive()
	{
		if (xmlhttp.readyState == 4) {
			//Mostra o HTML recebido
			retorno = xmlhttp.responseText;
			retorno = retorno.replace(/\+/g," ");
			retorno = unescape(retorno);
			//alert(fila[ifila]["func"] +  "('" + retorno + "')");
			if(retorno.substring(0,1) == ' '){
				retorno = retorno.substring(1,retorno.length);
			}
			retorno = retorno.replace(/\b|\f|\n|\r|\t/gi,'');
			retorno = retorno.substring(retorno.indexOf('>>>'),retorno.length)
			eval(fila[ifila]["func"] +  "('" + retorno + "')");
			//document.getElementById(fila[ifila][0]).innerHTML = retorno;
			//Roda o próximo
			ifila++;
			//alert("receive() = ifila: " + ifila);	
			if(ifila < fila.length){
				run();
			}else{
				ifila = 0;
				fila = [];
			}
		}
	}
}	
