// AJAX

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;
	
	var executer;
	if(param.executer) {
		executer = param.executer;
	}
	else {
		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];
	
	var list;
	switch(type)
	{
		case "single":
			if(elem.firstChild)
				list = elem.firstChild.nodeValue;
			break;
		
		case "list": // Взять списком содержимое тег
			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;
}




// Работа с формами

function form_class() {
		
	// Отправить форму
	// param - необработаный набор аргументов
	this.send = function(param) {
		if (!param)
			return false;
		// Если есть параметр запроса подтверждения
		if (param.confirm) {
			var result = confirm(param.confirm);
			if(!result)
				return false;
		}
		param=this.compile_param(param);
		
	    return this.request(param);
	}
	
	// Перейти по ссылке
	this.link = function(param) {
		if (!param)
			return false;
		// Если есть параметр запроса подтверждения
		if (param.confirm) {
			var result = confirm(param.confirm);
			if(!result)
				return false;
		}
		param=this.compile_param(param);
		if(param.url)
			document.location = param.url;
		return true;
	}
	
	// Обработать параметр
	this.compile_param = function(param) {
		if(param.url_add) {
			if(param.url)
				param.url = param.url + "&";
			else 
				param.url = "";
			param.url = param.url + param.url_add;
		}
			
		return param; 
	}
	
	// Обработка формы, если та задана
	this.request = function(param) {
		// Данные для POST
		if(param.form) {
			var elem = select_object(param.form);
			
			if(elem) {
				// Сменить адрес
				if(param.url) {
					elem.action = param.url;
				}
				// Метод
				if(param.method) {
					elem.method = param.method;
				}
				// Новые или измененные поля
				if(param.change) {
					this.change_element(param.form, param.change);
				}
				
				elem.submit();
				return true;
			}
		}
		return false;
	}
	
	// Присвоить значения присутсвующим в форме элементам или создать новые поля
	// change_list - массив, который должен прибавиться к форме [имя_поля, значение, ]
	this.change_element = function(uid_form, change_list) {
		var elem_form = select_object(uid_form);
		if(!elem_form)
			return false;
		if(is_array(change_list)) {
			for (var i=0; change_list.length>i; i+=2) {		
				var element_list = elem_form.elements;
				if (element_list[change_list[i]]) {
					element_list[change_list[i]].value = change_list[i+1];
				}
				else {
					var param = {type: "hidden", name:change_list[i], value:change_list[i+1]};
					var input = create_element ("INPUT", param);
					elem_form.appendChild(input);
				}
			}
		}
		return true;
	}
	
	// Проверка заполнения
	// form_name - имя формы, 
	// В форме проверяется все, что содержит атрибут need_check, как название используется атрибут need_check_title
	// имя email Всегда вызывает проверку по типу email
	// Все поля с непустым атрибутом need_clear предварительно очищаются
	this.check = function(form_uid) {
		var err_string="";
		var elem = select_object(form_uid);
		var need_check_title;
		var error;
		
		if(!elem)
			return false;
		
		elem = elem.elements;
				
		for (var i=0; elem.length > i; i++) {
			// Очистка предзаполненого поля
			var need_clear = get_attribute (elem[i], "need_clear");
			if(need_clear) {
				elem[i].value = "";
			}
			var need_check = get_attribute (elem[i], "need_check");
			error = false;
			if(need_check) {
				if(need_check=='email') {
					reg_mail=/[0-9a-z_]+@[0-9a-z_^.]+.[a-z]{2,3}/i;
					if (reg_mail.test(elem[i].value)==false) {
							error = true;
					}
				}
				else {
					if (get_value(elem[i]) == undefined || get_value(elem[i])=="") {// Для текстовых полей и select
						error = true;
					}
				}
				if(error) {
					// Если не была ранее ошибкой - сделать бордер красным
					if(elem[i].need_check_last_border==undefined) {
						elem[i].need_check_last_border = elem[i].style.borderColor;
						elem[i].style.borderColor = "red";
					}
					need_check_title = get_attribute (elem[i], "need_check_title");
					err_string = err_string+"- "+need_check_title+" <br>"; 	
				}	
				else {
					if(elem[i].need_check_last_border!=undefined)
						elem[i].style.borderColor = elem[i].need_check_last_border;
				}
			}
		}
		if (err_string!="") {
			err_string="<div style='text-align: left; padding: 20px;'>Неправильно заполнены следующие поля: <br><br>" + err_string + "</div>";
			dialog("Ошибка заполнения", err_string);
			//alert(err_string);
			return false;
		}
		return true;
	}
	
	// Проверить форму на наличие полей с необходимостью очистки, присвоить им события очистки
	this.compile_form  = function(form_uid) {
		var elem_form = select_object(form_uid);
		if(!elem_form)
			return false;
		
		elem = elem_form.elements;
		
		for (var i=0; elem.length > i; i++) {
			// Очистка предзаполненого поля
			var need_clear = get_attribute (elem[i], "need_clear");
			if(need_clear) {
				$(elem[i]).bind("click",formwork.clear_fc);
			}
		}
		return true;
	}
	
	// Статическая функция очистки поля 
	this.clear_fc = function(event)
	{
		var elem = event.target;
		set_value(this, "");
		$(elem).unbind("click", formwork.clear_fc);
		set_attribute (elem, "need_clear", "");
	}
}
var formwork = new form_class();
