function AutoSuggestControl(oTextbox , oTextboxId , oSelType , oSelMap , oProvider ){
	this.cur = -1;
	this.layer = null;
	this.timeout = null;
	this.provider = oProvider;
	this.textbox = oTextbox;
	this.textid = oTextboxId;
	this.seltype = oSelType;
	this.selmap = oSelMap;
	this.init();
}

AutoSuggestControl.prototype.autosuggest = function (aSuggestions, bTypeAhead){
	if(aSuggestions.length > 0){
		this.showSuggestions(aSuggestions);
	} else {
		this.hideSuggestions();
	}
}

AutoSuggestControl.prototype.createDropDown = function (){
	var oThis = this;

	this.layer = document.createElement("div");
	this.layer.className = "suggestions";
	this.layer.style.visibility = "hidden";
	this.layer.style.width = this.textbox.offsetWidth;

	this.layer.onmousedown =
	this.layer.onmouseup =
	this.layer.onmouseover = function (oEvent){
		oEvent = oEvent || window.event;
		oTarget = oEvent.target || oEvent.srcElement;

		if(oEvent.type == "mousedown"){
			 oThis.textid.value = oTarget.id;
			 oThis.textbox.value = oTarget.firstChild.nodeValue;
			 oThis.seltype.value = oTarget.alt;
			 oThis.selmap.value = '';
			 oThis.hideSuggestions();
		} else if(oEvent.type == "mouseover"){
			 oThis.highlightSuggestion(oTarget);
		} else {
			 oThis.textbox.focus();
		}
	}

	document.body.appendChild(this.layer);
}

AutoSuggestControl.prototype.getLeft = function () /*:int*/ {

	var oNode = this.textbox;
	var iLeft = 0;

	while(oNode.tagName != "HTML" && oNode.tagName != "BODY"){
		iLeft += oNode.offsetLeft;
		oNode = oNode.offsetParent;
	}

	return iLeft;
}

AutoSuggestControl.prototype.getTop = function () /*:int*/ {

	var oNode = this.textbox;
	var iTop = 0;

	while(oNode.tagName != "HTML" && oNode.tagName != "BODY"){
		iTop += oNode.offsetTop;
		oNode = oNode.offsetParent;
	}

	return iTop;
}

AutoSuggestControl.prototype.handleKeyDown = function (oEvent /*:Event*/){

	switch(oEvent.keyCode){
		case 38:
			this.previousSuggestion();
			break;
		case 40:
			this.nextSuggestion();
			break;
		case 17:
			break;
		case 27:
		case 13:
			//this.textbox.form.onsubmit = function(){return false;}
			this.clickNavigation();
			this.hideSuggestions();
			void(0);
			break;
	}

}

AutoSuggestControl.prototype.handleKeyUp = function (oEvent){
	var iKeyCode = oEvent.keyCode;

	if(iKeyCode == 8 || iKeyCode == 46){
		if(this.textbox.value.length>=3){
			var This = this;
			if(this.timeout){ clearTimeout(this.timeout); this.timeout=null; }
			this.timeout = setTimeout(function(){ This.provider.requestSuggestions(This, false); }, 300);
		}

	} else if(iKeyCode && (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123))){
	} else {
		if(this.textbox.value.length>=3){
			var This = this;
			if(this.timeout){ clearTimeout(this.timeout); this.timeout=null; }
			this.timeout = setTimeout(function(){ This.provider.requestSuggestions(This, true); }, 300);
		}
	}
}

AutoSuggestControl.prototype.hideSuggestions = function (){
	if(typeof this.selmap != "undefined")
	 if(this.selmap.name)
		if(typeof document.getElementById('a'+this.selmap.name) != "undefined")
		 document.getElementById('a'+this.selmap.name).style.display=(this.textid.value?'none':'');
	this.layer.style.visibility = "hidden";
	clearTimeout();
}

AutoSuggestControl.prototype.highlightSuggestion = function (oSuggestionNode){

	for(var i=0; i < this.layer.childNodes.length; i++){
		var oNode = this.layer.childNodes[i];
		if(oNode == oSuggestionNode){
			oNode.className = "current"
		} else if(oNode.className == "current"){
			oNode.className = "";
		}
	}
}

AutoSuggestControl.prototype.init = function (){
	var oThis = this;

	this.textbox.onfocus = this.textbox.ondblclick = this.textbox.onkeyup = function (oEvent){
		if(!oEvent){
			oEvent = window.event;
		}
		oThis.handleKeyUp(oEvent);

		if(oEvent.keyCode==13 || oEvent.keyCode==27) return false;
		oThis.textid.value = '';
		oThis.seltype.value = '';
		oThis.selmap.value = '';
	}

	this.textbox.onkeydown = function (oEvent){

		if(!oEvent)
			oEvent = window.event;

		oThis.handleKeyDown(oEvent);
		
		if(oEvent.keyCode==13 || oEvent.keyCode==27) return false;
		oThis.textid.value = '';
		oThis.seltype.value = '';
		oThis.selmap.value = '';
	}

	this.textbox.onkeypress = function (oEvent){
		if(!oEvent)
			oEvent = window.event;

		if(oEvent.keyCode==13 || oEvent.keyCode==27) return false;
		
		oThis.textid.value = '';
		oThis.seltype.value = '';
		oThis.selmap.value = '';
	}

	this.textbox.onblur = function (){
		oThis.hideSuggestions();
	}
	this.createDropDown();
}

AutoSuggestControl.prototype.clickNavigation = function (){
	var cSuggestionNodes = this.layer.childNodes;

	if(cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length){
		var oNode = cSuggestionNodes[this.cur];
		this.highlightSuggestion(oNode);
		this.textid.value = oNode.id;
		this.textbox.value = oNode.firstChild.nodeValue;
		this.seltype.value = oNode.alt;
		this.selmap.value = '';
	}
}

AutoSuggestControl.prototype.nextSuggestion = function (){
	var cSuggestionNodes = this.layer.childNodes;

	if(cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length-1){
		var oNode = cSuggestionNodes[++this.cur];
		this.highlightSuggestion(oNode);
		this.textid.value = oNode.id;
		this.textbox.value = oNode.firstChild.nodeValue;
		this.seltype.value = oNode.alt;
		this.selmap.value = '';
	}
}

AutoSuggestControl.prototype.previousSuggestion = function (){
	var cSuggestionNodes = this.layer.childNodes;

	if(cSuggestionNodes.length > 0 && this.cur > 0){
		var oNode = cSuggestionNodes[--this.cur];
		this.highlightSuggestion(oNode);
		this.textid.value = oNode.id;
		this.textbox.value = oNode.firstChild.nodeValue;
		this.seltype.value = oNode.alt;
		this.selmap.value = '';
	}
}

AutoSuggestControl.prototype.selectRange = function (iStart /*:int*/, iLength /*:int*/){
	if(this.textbox.createTextRange){
		var oRange = this.textbox.createTextRange();
		oRange.moveStart("character", iStart);
		oRange.moveEnd("character", iLength - this.textbox.value.length);
		oRange.select();
	} else if(this.textbox.setSelectionRange){
		this.textbox.setSelectionRange(iStart, iLength);
	}
	this.textbox.focus();
}

AutoSuggestControl.prototype.showSuggestions = function (aSuggestions /*:Array*/){

	var oDiv = null;
	this.layer.innerHTML = "";	//clear contents of the layer

	for(var i=0; i < aSuggestions.length; i++){
		oDiv = document.createElement("div");
		oDiv.id=aSuggestions[i][0];
		oDiv.appendChild(document.createTextNode(aSuggestions[i][1]));
		oDiv.alt=aSuggestions[i][2];
		oDiv.style.whiteSpace='nowrap';
		this.layer.appendChild(oDiv);
	}

	this.layer.style.left = this.getLeft() + "px";
	this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + "px";
	this.layer.style.visibility = "visible";
	this.layer.style.width = this.textbox.offsetWidth+"px";

}

AutoSuggestControl.prototype.typeAhead = function (sSuggestion /*:String*/){
	if(this.textbox.createTextRange || this.textbox.setSelectionRange){
		var iLen = this.textbox.value.length;
		this.textid.value = sSuggestion[0];
		this.textbox.value = sSuggestion[1];
		this.seltype.value = sSuggestion[2];
		this.selmap.value = '';
		this.selectRange(iLen, sSuggestion.length);
	}
}