// Базовый объект
var net = new Object();
// Состояния запроса
net.READY_STATE_UNINITIALIZED = 0;
net.READY_STATE_LOADING = 1;
net.READY_STATE_LOADED = 2;
net.READY_STATE_INTERACTIVE = 3;
net.READY_STATE_COMPLETE = 4;
// Конструктор
// key - Ключ запроса в массиве requestsHash
// method - метод отправки запроса (POST, GET)
// url - URL скрипта на сервере, который обработает запрос
// params - параметры запроса (test=1&flag=2)
// onload - callback-функция, обработчик после загрузки
// onerror - callback-функция, обработчик в случае ошибки
// contentType - тип контента запроса (text/html)
// headers - прочие заголовки, кроме content-type, например, Expires
net.ContentLoader = function(key, method, url, params, onload, onerror, contentType, headers) {
    this.hashKey = key; 
    this.unrequestBrowser = false;    								// Свойство для рапознавания браузеров, не поддерживающих request
    // request - объект
    this.request = null;
    this.onLoad = onload;
    this.onError = (onerror) ? onerror : this.defaultError;    		// Если её нет, вызывается дефолтный обработчик
    this.loadXMLDoc(method, url, params, contentType, headers);    	// Вызываем метод для генерации запроса

}
// Все методы записаны в прототип
net.ContentLoader.prototype = { // Methods
    // loadXMLDoc - метод, для генерации request-запроса
    loadXMLDoc : function(method, url, params, contentType, headers) {
        if (!method) method = "GET";
        if (!contentType && method == "POST") contentType = 'application/x-www-form-urlencoded';
		
		this.request = false;

		try {	// IE 7.0
			this.request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {	// IE 6.0
				this.request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {
				this.request = false;
			}
		}
		
		if (this.request === false && typeof XMLHttpRequest != 'undefined') { // Opera, FF, Gecko
			this.request = new XMLHttpRequest();
		} else if (this.request === false) {
			this.unrequestBrowser = true;
			return;
		}
		
        if (this.request) {
            try {
                this.request.open(method, url, true);	// Асинхронный запрос
                if (contentType) {
                    this.request.setRequestHeader('Content-Type', contentType);
                }
                if (headers) {
                    for (var h in headers) {
                        this.request.setRequestHeader(h, headers[h]);
                    }
                }
                var loader = this;
                this.request.onreadystatechange = function() {
                    loader.onReadyState.call(loader);
                }
                this.request.send(params);
            } catch (e) {
                this.onError.call(this);
            }
        }
    },
    // onReadyState - метод для обработки ответов сервера
    onReadyState : function() {
        var request = this.request;
        var ready = request.readyState;
        if (ready == net.READY_STATE_COMPLETE) {
            var httpStatus = request.status;
            if (httpStatus == 200 || httpStatus == 0) {
                this.onLoad.call(this);
            } else {
                this.onError.call(this);
            }
        }
    },
    // defaultError - метод обработки ошибок по умолчанию
    defaultError : function() {
        alert("error fetching data!" + "\n\nreadyState:" + this.request.readyState + "\nstatus: " + this.request.status + "\nheaders: " + this.request.getAllResponseHeaders());
    }
}
// Массив для хранения нескольких запросов
var requestsHash = [];
// Функция, создающая новый экземпляр объекта net.ContentLoader
// Записывает запросы в requestsHash
// Возвращает свойство unrequestBrowser
function setAjaxRequest(method, url, params, onload, onerror, contentType, headers) {
    // Check of necessary parameters
    if (!url) {
        alert("Necessary parameters are not specified");
        return;
    }
    requestsHash.push(new net.ContentLoader(requestsHash.length, method, url, params, onload, onerror, contentType, headers));
    return requestsHash[requestsHash.length - 1].unrequestBrowser;
}
