﻿var inputWithSuggestionsListDataArray = new Array();
var timeoutInterval = 800;
var loadingString = "Загрузка...";
var noDataString = "Данных не обнаружено.";
var errorString = "Ошибка. Пожалуйста, введите значение вручную.";
var browsers = { ie: 0, firefox: 1 };
var browser = createBrowserClass();

function InputWithSuggestionsListData()
{
	this.inputId = "";
	this.hiddenInputId = "";
	this.callbackUrl = "";
	this.callbackUrlParameters = null;
	this.timeoutID = 0;
	this.suggestionsListContainer = null;
	this.currentSuggestionIndex = 0;
	this.minSearchSymbolsCount = 1;
	this.width = 0;
	this.register = function()
	{
		if (typeof(this.callbackUrlParameters) == "string")
		{
			this.getCallbackUrlParameters = function() { return this.callbackUrlParameters;}
		}
		if (typeof(this.callbackUrlParameters) == "function")
		{
			this.getCallbackUrlParameters = function() {return this.callbackUrlParameters();}
		}
		inputWithSuggestionsListDataArray.push(this);
		var input = document.getElementById(this.inputId);
		input.setAttribute("autocomplete", "off");
		registerSuggestionsListControlPart(inputWithSuggestionsListDataArray.length - 1);
	}
}

function registerSuggestionsListControlPart(inputWithSuggestionsListDataIndex)
{
	var inputWithSuggestionsListData = inputWithSuggestionsListDataArray[inputWithSuggestionsListDataIndex];
	var input = document.getElementById(inputWithSuggestionsListData.inputId);
	browser.attachEventHandler(document, "onclick", function(e)
	{
		if (e.srcElement.id != inputWithSuggestionsListData.inputId)
		{
			destroySuggetionsList(inputWithSuggestionsListDataIndex);
		}
	});
	browser.attachEventHandler(input, "onkeyup", function(e)
	{
		if (!new Array(27, 13, 40, 38, 33, 34, 16, 17, 18).contains(e.keyCode))
		{
			var inputValue = document.getElementById(inputWithSuggestionsListData.inputId).value;
			if (inputWithSuggestionsListData.minSearchSymbolsCount <= inputValue.length)
			{
				startLoadingData(inputWithSuggestionsListDataIndex);
			}
			else
			{
				destroySuggetionsList(inputWithSuggestionsListDataIndex);
			}
		}
		if (input.value.length < inputWithSuggestionsListData.minSearchSymbolsCount)
		{
			clearHiddenInput(inputWithSuggestionsListDataIndex);
		}
	});
	browser.attachEventHandler(input, "onkeydown", function(e)
	{
		//Up Down
		if (e.keyCode == 40 || e.keyCode == 38)
		{
			var suggestionsListContainerScrollTop = inputWithSuggestionsListData.suggestionsListContainer.scrollTop;
			var suggestionsListContainerHeight = inputWithSuggestionsListData.suggestionsListContainer.offsetHeight;
			var suggestions = inputWithSuggestionsListData.suggestionsListContainer.childNodes[0].childNodes[0].childNodes;
			makeSuggestionsViewDefault(inputWithSuggestionsListDataIndex);
			var currentSuggestionIndex = inputWithSuggestionsListData.currentSuggestionIndex + ((e.keyCode == 40) ? 1 : -1);
			currentSuggestionIndex = (currentSuggestionIndex < 0) ? 0 : currentSuggestionIndex;
			currentSuggestionIndex = (suggestions.length <= currentSuggestionIndex) ? (suggestions.length - 1)  : currentSuggestionIndex;
			inputWithSuggestionsListData.currentSuggestionIndex = currentSuggestionIndex;
			suggestions[currentSuggestionIndex].childNodes[0].childNodes[0].className = "suggestionHover";
			var suggestionsHeight = 0;
			for (var i = 0; i < currentSuggestionIndex; i++)
			{
				suggestionsHeight += suggestions[i].offsetHeight;
			}
			if (suggestionsListContainerScrollTop + suggestionsListContainerHeight < suggestionsHeight + suggestions[currentSuggestionIndex].offsetHeight)
			{
				inputWithSuggestionsListData.suggestionsListContainer.scrollTop = suggestionsHeight - suggestionsListContainerHeight + suggestions[currentSuggestionIndex].offsetHeight;
			}
			if (suggestionsHeight < suggestionsListContainerScrollTop)
			{
				inputWithSuggestionsListData.suggestionsListContainer.scrollTop = suggestionsHeight;
			}
		}
		//PgUp
		if (e.keyCode == 33)
		{
			//TODO
		}
		//PgDn
		if (e.keyCode == 34)
		{
			//TODO
		}
		//Enter
		if (e.keyCode == 13)
		{
			if (inputWithSuggestionsListData.suggestionsListContainer.hasChildNodes && 
				0 < inputWithSuggestionsListData.suggestionsListContainer.childNodes.length &&
				0 < inputWithSuggestionsListData.suggestionsListContainer.childNodes[0].childNodes.length)
			{
				var suggestions = inputWithSuggestionsListData.suggestionsListContainer.childNodes[0].childNodes[0].childNodes;
				var suggestion = suggestions[inputWithSuggestionsListData.currentSuggestionIndex].childNodes[0].childNodes[0];
				document.getElementById(inputWithSuggestionsListData.inputId).value = suggestion.innerHTML.replace(/\&amp;/g, "&");
				document.getElementById(inputWithSuggestionsListData.hiddenInputId).value = suggestion.getAttribute("responseDataValue");
				destroySuggetionsList(inputWithSuggestionsListDataIndex);
				e.returnValue = false;
			}
		}
		if (e.keyCode == 27)
		{
			destroySuggetionsList(inputWithSuggestionsListDataIndex);
		}
	});
}

function clearHiddenInput(inputWithSuggestionsListDataIndex)
{
	document.getElementById(inputWithSuggestionsListDataArray[inputWithSuggestionsListDataIndex].hiddenInputId).value = "";
}

function destroySuggetionsList(inputWithSuggestionsListDataIndex)
{
	var inputWithSuggestionsListData = inputWithSuggestionsListDataArray[inputWithSuggestionsListDataIndex];
	inputWithSuggestionsListData.suggestionsListContainer.style.display = "none";
	clearSuggestionsListContainer(inputWithSuggestionsListDataIndex);
}

function makeSuggestionsViewDefault(inputWithSuggestionsListDataIndex)
{
	var inputWithSuggestionsListData = inputWithSuggestionsListDataArray[inputWithSuggestionsListDataIndex];
	var suggestions = inputWithSuggestionsListData.suggestionsListContainer.childNodes[0].childNodes[0].childNodes;
	for (var i = 0; i < suggestions.length; i++)
	{
		suggestions[i].childNodes[0].childNodes[0].className = "suggestion";
	}
}

Array.prototype.contains = function(item)
{
	for (var i = 0; i < this.length; i++)
	{
		if (this[i] == item)
		{
			return true;
		}
	}
	return false;
}

function initializeSuggestionsListContainers()
{
	for(var i = 0; i < inputWithSuggestionsListDataArray.length; i++)
	{
		var suggestionsListContainer = document.createElement("div");
		suggestionsListContainer.className = "suggestionsListContainer";
		var input = document.getElementById(inputWithSuggestionsListDataArray[i].inputId);
		var inputRect = input.getBoundingClientRect();
		var documentLeftScroll = document.documentElement.scrollLeft;
		var documentTopScroll = document.documentElement.scrollTop;
		suggestionsListContainer.style.left = (inputRect.left + document.documentElement.scrollLeft) + "px";
		suggestionsListContainer.style.top = (inputRect.top + input.offsetHeight + document.documentElement.scrollTop) + "px";
		suggestionsListContainer.style.width = ((0 < inputWithSuggestionsListDataArray[i].width) ? inputWithSuggestionsListDataArray[i].width : (input.offsetWidth - 2)) + "px";
		suggestionsListContainer.style.display = "none";
		document.body.appendChild(suggestionsListContainer);
		inputWithSuggestionsListDataArray[i].suggestionsListContainer = suggestionsListContainer;
	}
}

function createSuggestionsList(inputWithSuggestionsListDataIndex, responseData)
{
	var inputWithSuggestionsListData = inputWithSuggestionsListDataArray[inputWithSuggestionsListDataIndex];
	inputWithSuggestionsListData.currentSuggestionIndex = 0;
	clearHiddenInput(inputWithSuggestionsListDataIndex);
	var suggestionsListContainer = inputWithSuggestionsListData.suggestionsListContainer;
	clearSuggestionsListContainer(inputWithSuggestionsListDataIndex);
	if (responseData.length == 0)
	{
		suggestionsListContainer.innerHTML = noDataString;
	}
	var table = document.createElement("table");
	table.setAttribute("cellpadding", 0);
	table.setAttribute("cellspacing", 0);
	var tbody = document.createElement("tbody");
	table.appendChild(tbody);
	
	for (var i = 0; i < responseData.length; i++)
	{
		var suggestion = document.createElement("div");
		suggestion.innerHTML = responseData[i].text2;
		suggestion.setAttribute("responseDataText1", responseData[i].text1);
		suggestion.setAttribute("responseDataValue", responseData[i].value);
		var tr = document.createElement("tr");
		var td = document.createElement("td");
		tr.appendChild(td);
		td.appendChild(suggestion);
		tbody.appendChild(tr);
		suggestion.className = (i != 0) ? "suggestion" : "suggestionHover";
		suggestion.onmouseover = function()
		{
			makeSuggestionsViewDefault(inputWithSuggestionsListDataIndex)
			this.className = "suggestionHover";
		}
		suggestion.onmouseout = function()
		{
			this.className = "suggestion";
		}
		suggestion.onclick = function()
		{
			document.getElementById(inputWithSuggestionsListData.inputId).value = this.getAttribute("responseDataText1").replace(/\&amp;/g, "&");
			document.getElementById(inputWithSuggestionsListData.hiddenInputId).value = this.getAttribute("responseDataValue");
			suggestionsListContainer.style.display = "none";
			clearSuggestionsListContainer(inputWithSuggestionsListDataIndex);
		}
	}
	suggestionsListContainer.appendChild(table);
	table.style.width = suggestionsListContainer.offsetWidth - 21;
}

function clearSuggestionsListContainer(inputWithSuggestionsListDataIndex)
{
	var inputWithSuggestionsListData = inputWithSuggestionsListDataArray[inputWithSuggestionsListDataIndex];
	var suggestionsListContainer = inputWithSuggestionsListData.suggestionsListContainer;
	while (suggestionsListContainer.hasChildNodes && suggestionsListContainer.lastChild != null)
	{
		suggestionsListContainer.removeChild(suggestionsListContainer.lastChild);
	}
}

function loadData(inputWithSuggestionsListDataIndex)
{
	var inputWithSuggestionsListData = inputWithSuggestionsListDataArray[inputWithSuggestionsListDataIndex];
	var suggestionsListContainer = inputWithSuggestionsListData.suggestionsListContainer;
	suggestionsListContainer.style.display = "block";
	suggestionsListContainer.innerHTML = loadingString;
	var input = document.getElementById(inputWithSuggestionsListData.inputId).value;
	
	
	var callbackUrlParameters = inputWithSuggestionsListData.getCallbackUrlParameters();
	callbackUrlParameters = callbackUrlParameters + ((callbackUrlParameters == "") ? "" : "&") + "value=" + encodeURIComponent(input);
	//alert(inputWithSuggestionsListData.callbackUrl + "?" + callbackUrlParameters);
	$.ajax
	({
		type: "GET",
		url: inputWithSuggestionsListData.callbackUrl,
		data: callbackUrlParameters,
		success: function(msg)
		{
			eval(msg);
			createSuggestionsList(inputWithSuggestionsListDataIndex, responseData);
		},
		error: function(xhr)
		{
			suggestionsListContainer.innerHTML = errorString;
		},
		cache: false
	});
}

function startLoadingData(inputWithSuggestionsListDataIndex)
{
	var inputWithSuggestionsListData = inputWithSuggestionsListDataArray[inputWithSuggestionsListDataIndex];
	clearTimeout(inputWithSuggestionsListData.timeoutID);
	clearSuggestionsListContainer(inputWithSuggestionsListDataIndex);
	inputWithSuggestionsListData.timeoutID = setTimeout("loadData(" + inputWithSuggestionsListDataIndex + ")", timeoutInterval);
}

function IE()
{
	this.browser = browsers.ie;
	this.setOnloadEventHandler = function(eventHandler)
	{
		document.body.onload = eventHandler;
	}
	this.attachEventHandler = function(element, eventName, eventHandler)
	{
		element.attachEvent(eventName, 
			function() 
			{
				eventHandler(event); 
			}
		);
	}
}

function Firefox()
{
	this.browser = browsers.firefox;
	this.setOnloadEventHandler = function(eventHandler)
	{
		document.addEventListener("DOMContentLoaded", eventHandler, false);
	}
	this.attachEventHandler = function(element, eventName, eventHandler)
	{
		element.addEventListener(eventName.substring(2), 
			function(event) 
			{
				var customEvent = new FirefoxEvent(event.which, event.target);
				eventHandler(customEvent);
				if (!customEvent.returnValue)
				{
					event.preventDefault();
					event.stopPropagation();
				}
			}, 
			false
		);
	}
}

function FirefoxEvent(keyCode, srcElement)
{
	this.keyCode = keyCode;
	this.srcElement = srcElement;
	this.returnValue = true;
}

function createBrowserClass()
{
	if (0 <= navigator.appName.indexOf("Netscape"))
	{
		return new Firefox();
	}
	if (0 <= navigator.appName.indexOf("Explorer"))
	{
		return new IE();
	}
	return null;
}

