function Autosuggest(containerId)
	{
		
	if(typeof window.getNode != 'function')
		{
		alert("Для коректної роботи потрібен файл functions.js");
		return false;
		}

//	var elementsLimit=10;
	var elementName=containerId;
	this.container=getNode("container_"+containerId);	
	this.searchInput = getNode(containerId+"_view");
	var valueInput = getNode(containerId);
	this.container.style.width=this.searchInput.offsetWidth;
	//hideNode(this.container.id);
	setContainerHtml(this.container);
	var  autosuggest_marker = true;
	this.listDiv = getNode(this.container.id+'_listDiv');
	var searchInput=this.searchInput;
	var oldText="";
	var elementsArray= new Array();
	var timeout_id=0;
	var elementsCounter=0;
	var currentPosition=0;
	var currentElement=null;
	var isFocused=false;
	var container=this.container;
	var eventActions = new Array();
	var makeSearch=false;
	var fromValue=0;
	var oldSearchText="";
	var config= new Array();
	config['ajax_controller']=	'../ajax_get_form_sql/index.html';
	config['reactionDelay']=	1000;
	config['elementsLimit']=	20;
	config['not_found_text']=	"not found";
	config['typeOfGetData']=	"ajax";
	config['getDataArray']=		"";
	config['matchCase']=		false;
	config['checkDigit']=		true;
	config['after_select']=		function() {};//	функція яка викликається після вибору елемента списку
	config['debug']=		false;

	
	this.setConfig = function(name,value) 
		{config[name]=value;}

//	function setConfig(name,value)
//		{alert(name); config[name]=value; }
    
	this.getConfig = function(name) 
		{ return getConfig(name);  }	
    
	function getConfig(name) 
		{ return config[name]; }    

	function nextFocus()
		{
		counter=document.forms_component.elements.length;
		for(i=0; i<counter; i++)
			{
			if(document.forms_component.elements[i].id==searchInput.id)
				{
				for(j=i+1; j<counter; j++)
					{
					if(document.forms_component.elements[j].type!="hidden")
						{
						document.forms_component.elements[j].focus();
						break;
						}
					}
				return(true);
				}
			}
		}

    
	this.searchInput.onclick = function(e)	{ window.setTimeout(onBlurFunc,100); }

	this.searchInput.onfocus = function(e)	{ isFocused=true; }

	this.searchInput.onselect = function(e) {}

	this.searchInput.onblur = function(e) 
		{		
		hideNode(container.id+'_listDiv');
		isFocused=false;
		eventHandler('onBlur',getClassName(),searchInput.value)
		}
	
	var onBlurFunc = function()
		{
		
		hideNode(container.id+'_listDiv');
		currentElement=null;
		clearChilds();
		elementsArray= new Array();
		eventHandler('onTextInputClick',searchInput,'true');
		}
	
	this.listDiv.onmouseover=function(e) {}



	addEvent( this.searchInput, "keyup", function(e){thisKeyUp(e);} );

//	this.searchInput.onkeyup=function(e) {thisKeyUp(e); eval(this.searchInput.onkeyup);};

	function thisKeyUp(e)
		{
		var keyCode=getKeyCode(e);
		if(getKeyCode(e)==8 || getKeyCode(e)==46) // Backspace or Delete
			{
			oldText="";
			currentElement=null;
			valueInput.value="0";
			}

		if (!currentElement)
			{
			var trimedValue=trim(searchInput.value," ");
			if( oldText!=trimedValue || keyCode==40)
				{
				oldText=searchInput.value;
				clearTimeout(timeout_id);
				timeout_id = window.setTimeout(tmFunc,config["reactionDelay"]);
				}
			else if(searchInput.value=="" && keyCode==13)
				{				
				clearTimeout(timeout_id);
				timeout_id = window.setTimeout(tmFunc, 10);
				kPress(e);
				}
			}
		else
			{
			//currentElement=null;	
			oldText=searchInput.value;
			}
			
	    }	


	this.searchInput.onkeypress = function(e)
	{
		var keyCode=getKeyCode(e);
		if (config['checkDigit']==true)		
		{
			if(keyCode==13 || keyCode==48 || keyCode==49 || keyCode==50 || keyCode==51 || keyCode==52 || keyCode==53 || keyCode==54 || keyCode==55 || keyCode==56 || keyCode==57)									
				return false;
		}
		else
			if(keyCode==13)
				return false;			
	};


	

	function kPress(e)
	{
		if( !e ) 			
			if( window.event ) 
//Internet Explorer
				{ e = window.event; }

		var keyCode=getKeyCode(e);
		
		if (config['checkDigit']==true)		
			{
			switch( keyCode )
				{
				case 13:
				case 40:
				case 38:
				case 48:
				case 49:
				case 50:
				case 51:
				case 52:
				case 53:
				case 54:
				case 55:
				case 56:
				case 57:
					{
					
					if (keyCode==40)
						{
						if(currentPosition>0)
							{
							currentPosition--;
							makeSearch=false;
							}
						else
							{
							makeSearch=true;
							fromValue=fromValue+getConfig("elementsLimit");	
							}
						}
					else if(keyCode==38)
						{
						if(currentPosition<elementsCounter-1)
							{
							currentPosition++;
							makeSearch=false;
							}
						else
							{
							makeSearch=true;
							fromValue=fromValue-getConfig("elementsLimit");		
							if(fromValue<0)
								fromValue=0;
							}
						}
					else if(keyCode==13)
						{				
						currentPosition=elementsCounter-1;
						makeSearch=true;
						e.cancelBubble=true;
						config['after_select']();
						}
					else
						{				
						codeTypes=new Array();
						codeTypes[48]=10;
						codeTypes[49]=1;
						codeTypes[50]=2;
						codeTypes[51]=3;
						codeTypes[52]=4;
						codeTypes[53]=5;
						codeTypes[54]=6;
						codeTypes[55]=7;
						codeTypes[56]=8;
						codeTypes[57]=9;

						currentPosition=elementsCounter-codeTypes[keyCode];				
						makeSearch=true;
						e.cancelBubble=true;
						}


				var liElement=getNode(container.id+'_listLi'+currentPosition.toString());


				if(liElement)
					{
					makeSearch=false;
					if(makeSearch)
						{
	/*
						//clearChilds();
						getData(oldSearchText,fromValue,getConfig("elementsLimit"))
						var newLiElement=getNode(container.id+'_listLi'+currentPosition.toString());
						if(newLiElement)
							{
							//alert(container.id+'_listLi'+currentPosition.toString());
							newLiElement.className="autosuggestSelectetLi";
							searchInput.value=elementsArray[newLiElement.id]["text"];
							oldText=searchInput.value;
							currentElement=newLiElement;
							}
	*/
						}	
					else
						{
						clearSelection();
						eventHandler('onListItemOut', getClassName(), elementsArray[liElement.id])
						liElement.className="autosuggestSelectetLi";					
						if( elementsArray[liElement.id]["value"] > 0 )
							{
							searchInput.value=elementsArray[liElement.id]["text"];
							oldText=searchInput.value;
							}

						currentElement=liElement;
						eventHandler('onListItemSelect',getClassName(),elementsArray[liElement.id]);
						}

					}
// 

				if(keyCode==13 || keyCode==48 || keyCode==49 || keyCode==50 || keyCode==51 || keyCode==52 || keyCode==53 || keyCode==54 || keyCode==55 || keyCode==56 || keyCode==57)
					{
					if (currentElement!=null)
						{
						confirmSelect();
						config['after_select']();
						return false;					
						}
					}
				}
			}
		}
		else
		{
			if (keyCode==40)
			{
				if(currentPosition>0)
				{
					currentPosition--;
					makeSearch=false;
				}
				else
				{
					makeSearch=true;
					fromValue=fromValue+getConfig("elementsLimit");	
				}
			}
			else if(keyCode==38)
			{
				if(currentPosition<elementsCounter-1)
				{
					currentPosition++;
					makeSearch=false;
				}
				else
				{
					makeSearch=true;
					fromValue=fromValue-getConfig("elementsLimit");		
					if(fromValue<0)
						fromValue=0;
				}
			}
		else if(keyCode==13)
			{				
			currentPosition=elementsCounter-1;
			makeSearch=true;
			e.cancelBubble=true;
			config['after_select']();
			}
					
			
		var liElement=getNode(container.id+'_listLi'+currentPosition.toString());


		if(liElement && (elementsArray[liElement.id][active]==true))
			{
			makeSearch=false;
			clearSelection();
			eventHandler('onListItemOut', getClassName(), elementsArray[liElement.id])
			liElement.className="autosuggestSelectetLi";					
			searchInput.value=elementsArray[liElement.id]["text"];
			oldText=searchInput.value;
			currentElement=liElement;
			eventHandler('onListItemSelect',getClassName(),elementsArray[liElement.id])					
			}

		if(keyCode==13 )
			{
			if (currentElement!=null)
				{
				confirmSelect();
				config['after_select']();
				return false;					
				}
			}
		}
	}

	this.searchInput.onkeydown = function(e)
		{		
		var keyCode=getKeyCode(e);
		if (config['checkDigit']==true)		
		{
 			if(keyCode==13 || keyCode==48 || keyCode==49 || keyCode==50 || keyCode==51 || keyCode==52 || keyCode==53 || keyCode==54 || keyCode==55 || keyCode==56 || keyCode==57)
			{
			if (currentElement!=null)
				{				
				confirmSelect();			
				return false;	
				}
			}
			kPress(e);
			if(keyCode==13 || keyCode==48 || keyCode==49 || keyCode==50 || keyCode==51 || keyCode==52 || keyCode==53 || keyCode==54 || keyCode==55 || keyCode==56 || keyCode==57)
				return false;
		}
		else
		{
			if(keyCode==13 )
			{
			if (currentElement!=null)
				{				
				confirmSelect();			
				return false;	
				}
			}
			kPress(e);
			if(keyCode==13)
				return false;
		}
			
		}

	function confirmSelect()
		{
		hideNode(container.id+'_listDiv');
		//isFocused=false;
		//eventHandler('onBlur',getClassName(),searchInput.value);
		//searchInput.blur();
		eventHandler('onListItemOut',getClassName(),elementsArray[currentElement.id])
		//alert(elementsArray[currentElement.id]["text"]);
		if( elementsArray[currentElement.id][ 'value' ] >0 )
			{ searchInput.value=elementsArray[currentElement.id]["text"]; }
		startSearch(elementsArray[currentElement.id]);

		hideNode(container.id+'_listDiv');
		clearChilds();
		currentElement=null;
		}




	var tmFunc = function(text){onTextChange(searchInput.value)};
	
	function onTextChange(text) 
		{
		if(text=="")
			{ text=searchInput.value;}			

// це для виводу всього списку при натисканні keyDown
//		if(text!="")
//			{
				showNode(container.id+'_listDiv');
				clearChilds();
				valueInput.value="0";
				elementsCounter=0;
				currentPosition=0;
				getData(text,0,getConfig("elementsLimit"));
/*
			}
		else
			{
				hideNode(container.id+'_listDiv');
				clearChilds();
				valueInput.value="0";
			}
//*/
	    }


	function insertElementIntoList(text, value, visual, active)
		{
		var list= getNode(container.id+'_ulList');
		var newElement = document.createElement('li');
		
		newElement.id=container.id+'_listLi'+elementsCounter.toString();
		elementsArray[newElement.id]=new Array();
		elementsArray[newElement.id]["number"]=currentPosition;
		elementsArray[newElement.id]["text"]=text;
		elementsArray[newElement.id]["value"]=value;
		elementsArray[newElement.id]["visual"]=visual;
		elementsArray[newElement.id]["active"]=active;
		newElement.className="autosuggestUnSelectetLi";
		currentPosition=elementsCounter+1;
		elementsCounter++;		
		newElement.innerHTML = visual;
		list.insertBefore(newElement, list.firstChild);
		
		if(active==true)
			{
			onclick=function()
				{
				if(typeof(elementsArray[newElement.id])=="object")
					{
					searchInput.value=elementsArray[newElement.id]["text"];

					if(currentElement!=null)
						{ startSearch(elementsArray[currentElement.id]); }
					else
						{ startSearch(elementsArray[newElement.id]); }

//					alert(currentElement);
					clearChilds();
					currentElement=null;
					config['after_select']();
					}
				}
			
			if(newElement.onclick)
				{newElement.onclick=onclick; }
			else
				{ newElement.onmousedown=onclick; }

			newElement.onmouseover=function()
					{
					clearSelection();
					newElement.className="autosuggestHalfSelectetLi";
					currentPosition=elementsArray[newElement.id]["number"];
					eventHandler('onListItemSelect',getClassName(),elementsArray[newElement.id])
					//currentElement=newElement;
					}	
			newElement.onmouseout=function()
					{ eventHandler('onListItemOut',getClassName(),elementsArray[newElement.id]) }
			}
		
		}

	function liMouseClick(element)
		{
/*
		if(!searchInput)
			{}
alert(container);
//getNode(container+"_viev");
//*/

		searchInput.value=elementsArray[element.id]["text"];
		
		if(currentElement!=null)
			{ startSearch(elementsArray[currentElement.id]); }
		else
			{ startSearch(elementsArray[element.id]); }

//		alert(currentElement);
		clearChilds();
		currentElement=null;
	}


	function clearSelection()
		{
		var liList= getNode(container.id+'_ulList').childNodes;
		for(var i=0; i<liList.length; i++ )
			{ liList[i].className="autosuggestUnSelectetLi"; }
		}
	function clearChilds()
		{
		var liList= getNode(container.id+'_ulList');
		while ( liList.childNodes.length >= 1 )
		    { liList.removeChild(liList.firstChild); } 

		elementsArray=new Array();
		elementsCounter=0;
		currentPosition=getConfig("elementsLimit")-1;
		}

	this.clearChilds=function()
		{
		if(!isFocused)
			{
			hideNode(container.id+'_listDiv')
			clearChilds();			
			}
		}

	function getKeyCode(e) 
		{
		if( !e ) 
			{
			if( window.event ) 
//Internet Explorer
				{ e = window.event; }
			else 
//total failure, we have no way of referencing the event
				{ return false; }
			}
		if( typeof( e.keyCode ) == 'number'  ) 
//DOM
			{ e = e.keyCode; } 
		else if( typeof( e.which ) == 'number' ) 
//NS 4 compatible
			{ e = e.which; } 
		else if( typeof( e.charCode ) == 'number'  ) 
//also NS 6+, Mozilla 0.9+
			{ e = e.charCode; }
		else 
			{ return false; }
		return e;
		}	

	function startSearch(searchParams)
		{
		if(!searchParams["value"])
			{ searchParams["value"]=0; }

		valueInput.value=searchParams["value"];
		eventHandler('onItemSelect',getClassName(),searchParams);
		}

	function trim(str, chars) {
		return ltrim(rtrim(str, chars), chars);
	}
	 
	function ltrim(str, chars) {
		chars = chars || "\\s";
		return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
	}
	 
	function rtrim(str, chars) {
		chars = chars || "\\s";
		return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
	}
	function setContainerHtml(container)
		{
		if(container.offsetWidth>0)
			{ w=container.offsetWidth-2; }
		else
			{ w=100; }
		container.innerHTML="<div style='width:"+w+"px;' id='"+container.id+"_listDiv' class='listDiv'><ul id='"+container.id+"_ulList' class='ulList'></ul></div>";
		}


	function getData(searchText, from, limit)
		{
		if(config["typeOfGetData"]=="ajax")
			ajaxSearch(searchText,from,limit);
		else if(config["typeOfGetData"]=="array")
			{
			eval('elementsList='+config["getDataArray"]+'("'+searchText+'", "'+from+'", '+limit+');');

			ci=elementsList.length-1;
			counter=1;
			for(i=ci; i>0; i--)
				{
				insertElementIntoList(elementsList[i]["text"], elementsList[i]["vale"], '<NOBR>'+i+" "+elementsList[i]["visual"]+'</NOBR>', elementsList[i]["active"]);
				counter++;
				}
//*/
			}
		}

	function ajaxSearch(searchText,from,limit)
	{
		if(typeof window.sendAJAXRequest == 'function') 
			{
			var paramsString="";

			paramsString="autosuggest[node]="+config['node'];
			paramsString+='&autosuggest[value]='+searchText;
			paramsString+='&autosuggest[limit]='+limit;
			paramsString+='&autosuggest[from]='+from;
			
			if(config['additional_request_params'] instanceof Array)
				{
				var additional_request_params=config['additional_request_params'];
				for (var key in additional_request_params)
					{
					switch(additional_request_params[key])
						{
						case "__from_form__":
							if(additional_request_params["is_child_for_array"])
								{
								position=config['node'].substr(additional_request_params["default_name"].length+1)
								paramsString+='&autosuggest[additional_params]['+key+']='+getValue(key+"_"+position);
								}
							else
								{paramsString+='&autosuggest[additional_params]['+key+']='+getValue(key);}
							break;
						case "__from_var__":
							eval("temp="+additional_request_params[key]+";");

							if((typeof(temp)=="string") || (typeof(temp)=="number"))
								{paramsString+='&autosuggest[additional_params]['+key+']='+eval(additional_request_params[key]);}
							else if((typeof(temp)=="object") && (temp.length>-1))
								{
								alert(temp.length);
								}
							else
								{alert(additional_request_params[key]+" is not string, number or array");}
							break;
						default:
							paramsString+='&autosuggest[additional_params]['+key+']='+additional_request_params[key];
						}
					}
				
//alert(paramsString);
//				for(i=0; i<additional_request_params.length; i++)
//					{paramsString+='&autosuggest[additional_params]['+additional_request_params[i]+']='+getValue(additional_request_params[i]);}
				}




			oldSearchText=searchText;

			var ajaxController=getConfig('ajax_controller')
			//paramsString="";

			sendAJAXRequest(ajaxController,paramsString,'POST',
					function(responseText)
						{
//						alert(responseText);
						var resultArray=procesResponseData(responseText);
						}
			,
					function(responseStatus)
					{
						alert(responseStatus);
					}
			);
			
			//insertElementIntoList(searchText,0, searchText, true);
			}
		else
			{
				alert("Для коректної роботи потрібен файл ajax_object.js");
			}
	}


	function procesResponseData(responseText)
		{
		if( config[ 'debug' ] == true )
			{ alert( responseText ); }
		clearObjectItems();
		var JSONtext=responseText;
		var JSONobject=null;
		try
			{ JSONobject = JSON.parse(JSONtext); }
		catch(exception)
			{
			try
				{ JSONobject=eval('(' + JSONtext + ')'); }
			catch(exp)
				{
				if(responseText=="")
					{ alert("Cannot parse data"); }
				else
					{
					//alert(responseText);
					//insertElementIntoList("<span style='color:red'>"+config["not_found_text"]+"</span>",0, false);
					}
				}
			}

		if((JSONobject!=null) && (responseText!="null" || responseText!=""))
			{
			elementsList= new Array();
			i=1;

			if( JSONobject.length == 0 )
				{
				clearChilds();
				insertElementIntoList('<SPAN CLASS="autosuggestNotFound">'+config["not_found_text"]+"</span>", 0, '<SPAN CLASS="autosuggestNotFound">'+config["not_found_text"]+"</span>", false);
				}

			for ( var key in JSONobject )
				{
				if(!JSONobject[key][config["orow"]+"_visual"])
					{JSONobject[key][config["orow"]+"_visual"]=JSONobject[key][config["orow"]];}

				elementsList[i]=new Array();
				elementsList[i]["text"]=JSONobject[key][config["orow"]];
				elementsList[i]["vale"]=JSONobject[key][config["vrow"]];
				elementsList[i]["visual"]=JSONobject[key][config["orow"]+"_visual"];
				elementsList[i]["active"]=true;
				i++;
				}
			
			ci=i-1;
			counter=1;
			for(i=ci; i>0; i--)
				{
				insertElementIntoList(elementsList[i]["text"], elementsList[i]["vale"], '<NOBR>'+i+" "+elementsList[i]["visual"]+'</NOBR>', elementsList[i]["active"]);
				counter++;
				}
			}
		else if(responseText=="null" || responseText=="")
			{
			
			insertElementIntoList('<SPAN CLASS="autosuggestNotFound">'+config["not_found_text"]+"</span>",-999, '<SPAN CLASS="autosuggestNotFound">'+config["not_found_text"]+"</span>", false);
			}

		//insertElementIntoList(responseText,0);
	}

	function clearObjectItems()
		{
		//
		// не зрозумів для чого цей код.....але в IE він не працює....і здається все і без нього працює :)
		
/*
		var counter=0;
		for (var name in window) 
			{
		    	if(window[name] instanceof Autosuggest)
			   	{ window[name].clearChilds(); }
			 
			// if (typeof window[name] == 'object');
				// {
				// alert(window[name]);
				// if (window[name].autosuggest_marker != null)
					// { window[name].clearChilds(); }
				// }
			}
//*/
		}
		
	
	
	function getClassName()
		{ return (elementName+"Autosuggest"); }
	
	
	this.subscribe = function(event,fn) {
		eventActions[event] = fn;
	};
	this.unSubscribe = function(event) {
		eventActions[event]=null;
	};	
	
	var eventHandler=function(event,sender, eventArgs) 
	{
		if(eventActions[event] != null && eventActions[event] != undefined) 
		{
			eventActions[event](sender, eventArgs);
		}
		else 
		{
			//alert('There was no function subscribed to the ' + sender.name + ' event!');
		}
	}

}
