var store_function_array = new Array();

function store_function (str_function)
{
	store_function_array[store_function_array.length] = str_function;
}
function store_function_execute ()
{
	var i;
	for (i=0; i < store_function_array.length; i++) {
		eval(store_function_array[i]);
	}
}


function ajax_class() {
	
this.req = null;
this.query = new Array();
this.time_out = null;
this.param = null;
	
// Работа с очередью
// param - параметр
this.query_request = function (param)
{
	if(this.param==null) { // Если нет текущего выполняемого
		this.param = param;
		this.ajax_send(param);
	}
	else {
		this.query.push(param); // Добавить в конец очереди
		return false;
	}
	return true;
}

this.set_timeout = function()
{
	//this.time_out = setTimeout( ajax.handle_error, 20000);
}
this.clear_timeout = function()
{
	if (this.time_out)
		clearTimeout(this.time_out);
}
// Если Timeout  (Внешний вызов)
this.handle_error = function (message)
{
	ajax.finish();
	if(message)
		alert(message);
}
// Все сбросить
this.finish = function ()
{
	this.clear_timeout();
	this.req.abort();
	setTimeout(ajax.next_query, 100);
	return true;
}
// Следующий элемент в очереди (Внешний вызов)
this.next_query = function()
{
	if(is_array(ajax.query) && ajax.query.length>0) {
		param_next = ajax.query.shift();
		ajax.param = param_next;
		ajax.ajax_send(param_next);
	}
	else
		ajax.param = null;
}



// Ассинхронное обращение get
// param - необработаный набор аргументов
this.get = function(param) {
	if (!param)
		return false;
	if (param.confirm) {
		var result = confirm(param.confirm);
		if(!result)
			return false;
	}
	param=this.compile_param(param, "GET");
	
    return this.query_request(param);
}
// Ассинхронное обращение post
this.post = function(param) {
	if (!param)
		return false;
	if (param.confirm) {
		var result = confirm(param.confirm);
		if(!result)
			return false;
	}
	param=this.compile_param(param, "POST");
	
    return this.query_request(param);
}
// Обработать параметр
this.compile_param = function(param, method)
{
	param.method = method;
	// Данные для POST
	if(param.form) {
		param.data = this.form_to_data({form: param.form});
		// Если нет адреса - использовать форму
		if(!param.url)
			param.url = select_object({form: param.form}).action
	}
	if(param.url_add) {
		if(param.url)
			param.url = param.url + "&";
		else 
			param.url = "";
		param.url = param.url + param.url_add;
	}
	// Функция обработки
	if(!param.processing)
		param.processing = this.default_processing;
				
	// Функция обработки
	if(param.executer && typeof(param.executer) == "string") {
		if(param.executer=="search_holder")
			param.executer = ajax.executer_search_holder;
	}
	
	return param; 
}
// Данные из формы в переменную для отправки
this.form_to_data = function(formname_uid)
{
	var form_elements = select_object(formname_uid).elements;
	var data_post = "";
	if (form_elements && form_elements.length) {
		for (i=0; i<form_elements.length; i++)  {
			var res = true;
			if(!form_elements[i].name) 
				res = false;
			if(form_elements[i].type=="checkbox" && form_elements[i].checked!=true)
				res = false;
						
			if(res) {
				if (data_post!="")
					data_post+="&";
				data_post += form_elements[i].name + "=" + encodeURIComponent( form_elements[i].value );
			}
		}
	}
	return data_post;
}

// Запуск
// param - Обработаный набор аргументов
this.ajax_send = function(param)
{
	if (param.method == "GET") {
		param.data = null;
	}
	
	if (param.simple==true) {
		document.location = param.url;
		return true;
	}

    if (window.XMLHttpRequest) {		// для "родного" XMLHttpRequest
		this.req = new XMLHttpRequest();
		var req_type = 0;
    } else if (window.ActiveXObject) { 	// для версии с ActiveX
        this.req = new ActiveXObject("Microsoft.XMLHTTP");
		var req_type = 1;
    }
    if (this.req) {
    	this.req.onreadystatechange = param.processing;
        this.req.open(param.method, param.url+"&ajax=on", true);
        
     	if (param.method == "GET") {
     		if(req_type==1)
      			this.req.send();
      		else
      			this.req.send(param.data);
      	}
      	else {
      	    this.req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      		this.req.send(param.data);
      	}
    	this.set_timeout();
	
		return true;
   }
   return false;
}
// Получить результат (Внешний вызов)
this.default_processing = function() {
	var req = ajax.req;
    if (req.readyState == 4) {
		var param = ajax.param;
		var status = req.status;
		var response = req.responseXML;
		ajax.finish(); // С этого места локальна
		
        // для статуса "OK"
        if (status == 200) 
           	ajax.build_result(response, param);     
		// Редирект
		else if (status == 302 )
			alert("Страница переместилась");
		else 
            alert("Страница не найдена");
    }
}
// Обработать результат
this.build_result = function(result, param) {
	if(!result)
		return false;
	
	if(param.executer) {
		var executer = param.executer;
	}
	else {
		var executer = this.executer_default;
	}
	var data = new Array();
	data['redirect'] = select_tag(result, 'redirect');
	data['content'] = select_tag(result, 'content');
	data['response'] = select_tag(result, 'response', 'list');
	data['parametr'] = param;
	
	return executer(data);
}
// Обработчик полученых данных по-умолчанию
this.executer_default = function (data)
{
	if(data['redirect']) {
		ajax.get( {tag: data['parametr'].tag, url:data['redirect']} );
	}
	else if(data['parametr'].tag) {
		var elem = select_object(data['parametr'].tag);
		if(elem) {
			elem.innerHTML=data['content'];
		}
		store_function_execute();
	}
	
	return true;
}
// Обработчик полученых данных по-умолчанию
this.executer_search_holder = function (data)
{
	ajax.post( {tag: data['parametr'].tag, form:"search_holder"} );

	return true;
}
	
}
var ajax = new ajax_class();

// Получить данные из XML
function select_tag(source, id, type)
{
	type = type || "single";
	elem = source.getElementsByTagName(id);
	if (!elem || elem.length!=1)
		return null;
		
	elem = elem[0];
	
	switch(type)
	{
		case "single":
			var list;
			if(elem.firstChild)
				list = elem.firstChild.nodeValue;
			break;
		
		case "list": // Взять списком содержимое тег
			var list = new Array();
			elem = elem.childNodes;
			for(var i=0; i < elem.length; i++) {
				var cur_elem = elem.item(i);
				if(cur_elem.nodeType != "TEXT_NODE" && cur_elem.firstChild)
					list[cur_elem.tagName] = cur_elem.firstChild.nodeValue;
			}
			break;
	}
		
	return list;
}
