HTTP={};
// Попробуем использовать следующие функции, создающие объект XMLHttpRequest.
HTTP._factories = [
	function() { return new XMLHttpRequest(); },
	function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
	function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];
// Когда будет обнаружена работоспособная функция, она будет сохранена здесь.
HTTP._factory = null;
// Создает и возвращает новый объект XMLHttpRequest.
//
// При первом обращении к функции опробываются все функции из списка, пока
// не будет найдена та, что вернет непустое значение и не возбудит исключение.
// После того как будет обнаружена работоспособная функция, ссылка на нее
// запоминается для последующего использования.
//
HTTP.encodeFormData = function(data) {
	var pairs = [];
	var regexp = /%20/g; // Регулярное выражение, соответствующее закодированному пробелу
	for(var name in data) {
		var value = data[name].toString();
		// Создать пару имя/значение, но сначала имя и значение закодировать.
		// Практически все, что нам требуется, выполняет глобальная функция
		// encodeURIComponent, но она превращает пробелы в виде %20 вместо
		// требуемого нам "+". Исправить это можно с помощью String.replace()
		var pair = encodeURIComponent(name).replace(regexp,"+") + '=' +
		encodeURIComponent(value).replace(regexp,"+");
		pairs.push(pair);
	}
	// Объединить все пары в строку, разделяя их символами &
	return pairs.join('&');
};
HTTP.newRequest = function() {
	  if (HTTP._factory != null) return HTTP._factory();
	  
	  for(var i = 0; i < HTTP._factories.length; i++) {
		  try {
			  var factory = HTTP._factories[i];
			  var request = factory();
			  if (request != null) {
				 HTTP._factory = factory;
				 return request;
			   }
		  }
		  catch(e) { continue;   }
	   }
// Если попав сюда, сценарию не удалось обнаружить подходящую функцию для создания
// объекта, необходимо возбудить исключение в этом и всех последующих вызовах.
	HTTP._factory = function() {
		throw new Error("Объект XMLHttpRequest не поддерживается");
	}
	HTTP._factory(); // Возбудить исключение
}

HTTP.get = function(url, options) {

	var request = HTTP.newRequest();
	var n = 0;
	var timer;
	if (options.timeout)
	timer = setTimeout(function() {
			request.abort();
			if (options.timeoutHandler)
		    	options.timeoutHandler(url);
			},
			options.timeout);
	request.onreadystatechange = function() {
		if (request.readyState == 4) {
				if (timer) clearTimeout(timer);
	          if (request.status == 200) {	
				options.callback(request.responseText);
			}
		else {
			if (options.errorHandler)
			options.errorHandler(request.status,request.statusText);
			else callback(null);
			}
	   }
	  else if (options.progressHandler) {
 		options.progressHandler();
	  }
   }
	var target = url;
	if (options.parameters)
		target += "&" + HTTP.encodeFormData(options.parameters)
	
	request.open("GET", target);
	request.send(null);
};

HTTP.post = function(url, values) {
	var request = HTTP.newRequest();
	request.onreadystatechange = function() {
	if (request.readyState == 4) {
		if (request.status == 200) {
			values.callback(request.responseText);
		}
		  else {
		 	 if (values.errorHandler) values.errorHandler(request.status,request.statusText);
			 else callback(null);
				}
	  }else if (values.progressHandler) {
 		values.progressHandler();
	  }
		
	}
	
	request.open("POST", url);
	// Этот заголовок сообщает серверу, как интерпретировать тело запроса.
	request.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
	// Вставить в тело запроса имена и значения свойств объекта
	// и отправить их в теле запроса.
	request.send(HTTP.encodeFormData(values.parameters));
};
