self.AjaxX = function() {
	// PRIVATE/PRIVATE STATIC properties
	var IE = (window.ActiveXObject !== undefined);
	var _request;
	var _requests = [];
	var _state = 4;

	// PRIVATE methods
	var create = function() {
		try {
			_request = new XMLHttpRequest();
		}
		catch (excGeneral) {
			try {
				_request = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (excMicrosoft) {
				try {
					_request = new ActiveXObject("Msxml2.XMLHTTP");
				}
				catch (excMicrosoft2) {
					_request = null;

					alert("Não foi possível criar o objeto \"XMLHttpRequest\"!\nAtualize seu navegador:\n\n" + excMicrosoft2 + "\n" + excMicrosoft + "\n" + excGeneral);
				}
			}
		}
	};
	
	/*
	* Converte uma String para XML
	*/
	var toXml = function(str) {
		var xmlObject, xml;

		xml = null;
		//str = str.split("\n").join(""); // remove as quebras de linha
		
		if (str.match(/^<\?\s*xml/) !== null) {
			if (IE) {
				xml = new ActiveXObject("Microsoft.XMLDOM");
				xml.async = "false";
				xml.loadXML(str);
				
				if (xml.parseError.errorCode === 0) {
					xml.removeChild(xml.firstChild); // para igualar ao Firefox (sem o 1º nó)
				}
				else xml = xml.parseError.reason;
			}
			else {
				xmlObject = new DOMParser();
				xml = xmlObject.parseFromString(str, "text/xml"); // executa incondicionalmente
			}
		}
	
		return xml;
	};
	
	var process = function(url, params) {
		
		if(params == null) params = {};
		var url = url;
		var postData = (params.postData !== undefined) ? params.postData : "";
		var method = (postData !== "") ? "post" : ((params.method !== undefined) ? params.method.toLowerCase() : "get");
		var async = (params.async !== undefined) ? params.async : true;
		var onComplete = (params.onComplete !== undefined) ? params.onComplete : function(){};
		var onProcess = (params.onProcess !== undefined) ? params.onProcess : function(){};

		create();
		
		_request.onreadystatechange = function() {
			_state = _request.readyState;
			onProcess({state: _state});

			if (_state === 4) {
				var text = _request.responseText;
				
				onComplete({text: text, xml: toXml(text)});

				if (_requests.length > 0) {
					var obj = _requests.shift(); // remove o 1º elemento da fila
					
					process(obj.url, obj.params); // executa o elemento removido
				}
			}
		};

		try {
			_request.open(method, url, async);

			if (postData !== "") _request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

			_request.send(postData);
		}
		catch (exception) {
			var o = "";

			if (IE) for (var i in exception) o += i + ": " + exception[i] + "\n";
			else o = exception;
			
			alert("ERRO:\n" + o);
		}
	};
	
	// PUBLIC methods
	this.execute = function(url, params) {
		if (_state < 4) _requests.push({url: url, params: params});
		else process(url, params);
	};
};
