//Start Suggestion Class
function suggestion(id,txt,config) {
	if (typeof config == "undefined") {
		this.config = new suggestion.Config();
	} else {
		this.config = config;
	};

	this.id = id;
	this.curItem = -1;
	this.curNode = null;
	this.suggestDiv = null;
	this.iframeBkg = null;
	this.xmlRequest = null;
	this.hideEvent = null;
	this.keyCode = null;
	
	this.txt = txt;

	this.init();
};


suggestion.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
suggestion.isMSIE5 = suggestion.isMSIE && (navigator.userAgent.indexOf('MSIE 5') != -1);
suggestion.isMSIE5_0 = suggestion.isMSIE && (navigator.userAgent.indexOf('MSIE 5.0') != -1);
suggestion.isGecko = navigator.userAgent.indexOf('Gecko') != -1;
suggestion.isOpera = navigator.userAgent.indexOf('Opera') != -1;

//Suggestion Mode
suggestion.BeginWord = 1;
suggestion.PartialWord = 2;

suggestion.Config = function () {
	this.version = '0.1';
	this.scriptURL = '';
	this.className = '';
	this.itemHoverClass = '';
	this.itemNormalClass = '';
	this.width = null;
	this.minWordLength = 0;
	
	this.mode = suggestion.BeginWord;
	
	this.maxItem = 10;
	this.itemHeight = 16;
	
	this.processResponse = null;
	this.getItemText = null;	//Get Item Dislay Text for Auto Fill Text
	this.createItem = null;
	this.getItemValue = null;
};

suggestion.prototype.init = function () {
	var obj = this;
	
	//Disable autocomplete feature;
	this.txt.setAttribute("autocomplete","off");
	
	//Create Suggestion Div
	this.suggestDiv = document.createElement("DIV");
	this.suggestDiv.id = this.id + '_div';
	this.suggestDiv.style.position = "absolute";
	this.suggestDiv.style.top = '0px';
	this.suggestDiv.style.left = '0px';
	
	if (obj.config.width) {
		this.suggestDiv.style.width = obj.config.width + "px";
	}else {
		this.suggestDiv.style.width = this.txt.offsetWidth + "px";
	};
	
	this.suggestDiv.style.visibility = 'hidden';
	this.suggestDiv.className = this.config.className;
	if (suggestion.isGecko || suggestion.isOpera) this.suggestDiv.style.overflow = "auto";
	
	//Prepare DIV Event
	suggestion.addEvent(this.suggestDiv,"focus", function (event) {
				 return obj.OnFocus(suggestion.is_ie ? window.event : event);
			 });

	suggestion.addEvent(this.suggestDiv,"blur", function (event) {
				 return obj.OnBlur(suggestion.is_ie ? window.event : event);
			 });
	
	document.body.appendChild(this.suggestDiv);

	//Initail IFrame to Fix Overlap with select
	this.iframeBkg = document.createElement("IFRAME");
	this.iframeBkg.id = this.id + '_frame';
	this.iframeBkg.src = 'javascript:false';
	this.iframeBkg.style.position = "absolute";
	this.iframeBkg.style.top = '0px';
	this.iframeBkg.style.left = '0px';

	if (obj.config.width) {
		this.iframeBkg.style.width = obj.config.width + "px";
	}else {
		this.iframeBkg.style.width = this.txt.offsetWidth + "px";
	};

	this.iframeBkg.style.display = 'none';

	document.body.appendChild(this.iframeBkg);

	this.setPosition();
	
	//Prepate TextBox Event
	suggestion.addEvent(this.txt,"keyup", function (event) {
				 return obj.OnKeyUp(suggestion.is_ie ? window.event : event);
			 });

	suggestion.addEvent(this.txt,"keydown", function (event) {
				 return obj.OnKeyDown(suggestion.is_ie ? window.event : event);
			 });

	suggestion.addEvent(this.txt,"blur", function (event) {
				 return obj.OnBlur(suggestion.is_ie ? window.event : event);
			 });

	suggestion.addEvent(this.txt,"focus", function (event) {
				 return obj.OnFocus(suggestion.is_ie ? window.event : event);
			 });

	//Prepare Window Event
	suggestion.addEvent(window,"resize", function (event) {
				 return obj.OnResize(suggestion.is_ie ? window.event : event);
			 });
};

suggestion.prototype.OnKeyUp = function (e) {
	var obj = this;

	this.keyCode = e.keyCode;
	if ((e.keyCode != 40) && (e.keyCode != 38)) {
		if ((e.keyCode == 13) || (e.keyCode == 27)) {
			obj.suggestDiv.style.visibility = 'hidden';
			if (!suggestion.isOpera) obj.iframeBkg.style.display = 'none'
		} else {
			obj.GetSuggestion();
		};
	};
};

suggestion.prototype.OnKeyDown = function(e) {
	var obj = this;

	if ((e.keyCode == 40) && (obj.suggestDiv.style.visibility == 'visible')) {
		//Key Down
		if (obj.curNode) {
			obj.curNode.className = obj.config.itemNormalClass;
		};
		
		if (obj.suggestDiv.childNodes.length > 0) {
			if (obj.curItem < (obj.suggestDiv.childNodes.length - 1)) {
				if (obj.curItem > -1) {
					obj.suggestDiv.childNodes[obj.curItem].className = obj.config.itemNormalClass;
				};
				
				obj.curItem = obj.curItem + 1;

				obj.suggestDiv.childNodes[obj.curItem].className = obj.config.itemHoverClass;
				
				obj.txt.value = obj.config.getItemValue(obj.suggestDiv.childNodes[obj.curItem]);
				
				obj.suggestDiv.scrollTop = obj.curItem * 16;
			};
		};
		
		e.cancelBubble=true;
		e.returnValue=false;
	}else if ((e.keyCode == 38) && (obj.suggestDiv.style.visibility == 'visible')) {
		//Key Up
		if (obj.curNode) {
			obj.curNode.className = obj.config.itemNormalClass;
		};

		if (obj.suggestDiv.childNodes.length > 0) {
			if (obj.curItem > 0) {
				if (obj.curItem > -1) {
					obj.suggestDiv.childNodes[obj.curItem].className = obj.config.itemNormalClass;
				};
				
				obj.curItem = obj.curItem - 1;

				obj.suggestDiv.childNodes[obj.curItem].className = obj.config.itemHoverClass;

				obj.txt.value = obj.config.getItemValue(obj.suggestDiv.childNodes[obj.curItem]);

				obj.suggestDiv.scrollTop = obj.curItem * 16;
			};
		};
		
		e.cancelBubble=true;
		e.returnValue=false;
	};
};

suggestion.prototype.OnFocus = function (e) {
	var obj = this;

	clearTimeout(obj.hideEvent);
};

suggestion.prototype.OnBlur = function (e) {
	var obj = this;
	obj.hideEvent = setTimeout("suggestion.hideSuggestion('" + obj.id + "');",100);
};

suggestion.prototype.OnMouseOut = function(e,outItem) {
	var obj = this;

	obj.curNode = null;
	outItem.className = obj.config.itemNormalClass;
};

suggestion.prototype.OnMouseOver = function(e,overItem) {
	var obj = this;
	
	if (obj.curItem != -1) {
		obj.suggestDiv.childNodes[obj.curItem].className = obj.config.itemNormalClass;
	};
									
	obj.curItem = -1;
	obj.curNode = overItem;

	overItem.className = obj.config.itemHoverClass;
};

suggestion.prototype.OnResize = function (e){
	this.setPosition();
};

suggestion.prototype.setPosition = function () {
	var xPos,yPos;
	
	xPos = this.findPosX();
	yPos = this.findPosY();
	
	this.suggestDiv.style.top = yPos + this.txt.offsetHeight + 'px';
	this.iframeBkg.style.top = yPos + this.txt.offsetHeight + 'px';

	if ((xPos + this.suggestDiv.offsetWidth) > document.body.clientWidth) {
		xPos = document.body.clientWidth - this.suggestDiv.offsetWidth - (suggestion.isMSIE?20:5);
	};

	this.suggestDiv.style.left = xPos + 'px';
	this.iframeBkg.style.left = xPos + 'px';
};

suggestion.prototype.findPosX = function () {
	var obj = this.txt;

    var curleft = 0;
    if (obj.offsetParent) {
        while (obj.offsetParent) {
            curleft += obj.offsetLeft;
            obj = obj.offsetParent;
        };
    } else if (obj.x) {
        curleft += obj.x;
    };
    return curleft;
};

suggestion.prototype.findPosY = function () {
	var obj = this.txt;

    var curtop = 0;
    if (obj.offsetParent) {
        while (obj.offsetParent) {
            curtop += obj.offsetTop;
            obj = obj.offsetParent;
        };
    } else if (obj.y) {
        curtop += obj.y;
    };
    return curtop;
};

suggestion.hideSuggestion = function(id) {
	if (document.getElementById(id + '_div')) {
		document.getElementById(id + '_div').style.visibility = 'hidden';
		if (!suggestion.isOpera) document.getElementById(id + '_frame').style.display = 'none';
	}
};

suggestion.prototype.OnReadyStateChange = function(response){
	var obj = this;

	if(response.readyState==4 && response.responseText){
		obj.generateSuggest(obj.config.processResponse(response.responseText));
	};
};

suggestion.prototype.OnSelectItem = function(e,item) {
	var obj = this;
	obj.txt.value = obj.config.getItemValue(item);
};

suggestion.prototype.generateSuggest = function(dataList) {
	var obj = this;

	obj.curItem = -1;

	while(obj.suggestDiv.childNodes.length>0)
		obj.suggestDiv.removeChild(obj.suggestDiv.childNodes[0]);
		
	if (dataList && dataList.length > 0) {
		if (dataList.length > obj.config.maxItem) {
			//alert((obj.config.maxItem * obj.config.itemHeight) + "px");
			obj.suggestDiv.style.height = (obj.config.maxItem * obj.config.itemHeight) + "px";
		}else {
			obj.suggestDiv.style.height = (dataList.length * obj.config.itemHeight) + "px";
		};

		for (i = 0;i < dataList.length;i++) {
			var wd = obj.config.createItem(dataList[i]);
			wd.className = obj.config.itemNormalClass;
			//wd.onmousedown = function () {onSelectItem(txt,this);};
			wd.onmousedown = function (event) {
						 return obj.OnSelectItem(suggestion.is_ie ? window.event : event,this);
					 };
			wd.onmouseover = function (event) {
						 return obj.OnMouseOver(suggestion.is_ie ? window.event : event,this);
					 };
			wd.onmouseout = function (event) {
						 return obj.OnMouseOut(suggestion.is_ie ? window.event : event,this);
					 };

			obj.suggestDiv.appendChild(wd);
		};
		
		obj.iframeBkg.style.height = obj.suggestDiv.offsetHeight;
		
		obj.suggestDiv.style.visibility = 'visible';
		if (!suggestion.isOpera) obj.iframeBkg.style.display = 'block';
		
		if (obj.config.mode == suggestion.BeginWord) obj.autoSelect(obj.suggestDiv.firstChild);
	};
};

suggestion.prototype.autoSelect = function(firstItem) {
	var userText;
	
	var mb=false;
	switch(this.keyCode){
		case 8:case 33:case 34:case 35:case 35:case 36:case 37:case 39:case 45:case 46:
			mb=true;
			break;
		default:
			break
	}

	if (!mb) {
		if (this.config.getItemValue) {
			this.config.getItemValue(firstItem);
		}
		
		if (this.config.getItemText) {
			userText = this.txt.value;
			this.txt.value = this.config.getItemText(firstItem);
		}
	
		if (this.txt.createTextRange || this.txt.setSelectionRange) {
			if(this.txt.createTextRange){
				var u=this.txt.createTextRange();
				u.moveStart("character",userText.length);
				u.select()
			}else if(this.txt.setSelectionRange){
				this.txt.setSelectionRange(userText.length,this.txt.value.length)
			}
		}
	}
}

suggestion.prototype.GetSuggestion = function(){
	var obj = this;
	
	if (obj.txt.value && obj.txt.value != '' && (obj.txt.value.length >= obj.config.minWordLength)) {
		selectLocation = '';
		
		if(obj.xmlRequest && obj.xmlRequest.readyState != 0){
			obj.xmlRequest.abort();
		};

		obj.xmlRequest = suggestion.CreateXMLHttp();
		
		if(obj.xmlRequest){
			obj.xmlRequest.open("GET",obj.config.scriptURL + escape(obj.txt.value) ,true);
			
			obj.xmlRequest.onreadystatechange = function() {obj.OnReadyStateChange(obj.xmlRequest) };
			
			obj.xmlRequest.send(null);
		};
	}else {
		obj.suggestDiv.style.visibility = 'hidden';
		if (!suggestion.isOpera) obj.iframeBkg.style.display = 'none';
		obj.suggestDiv.innerHTML = '';
	};
};

suggestion.addEvent = function (obj, name, handler) {
	// Browser check
	if (suggestion.isMSIE)
		obj.attachEvent("on" + name, handler);
	else
		obj.addEventListener(name, handler, false);
};

suggestion.CreateXMLHttp = function(){
	var C=null;
	try{
		C=new ActiveXObject("Msxml2.XMLHTTP");
	}catch(e){
		try{
			C=new ActiveXObject("Microsoft.XMLHTTP");
		}catch(sc){
			C=null;
		};
	};
	
	if(!C&&typeof XMLHttpRequest!="undefined"){
		C=new XMLHttpRequest();
	};
	
	return C;
};

suggestion.unescapeHtml = function(iStr) {
	var strResult;
	strResult = iStr;
	strResult = strResult.replace("&nbsp;"," ");
	strResult = strResult.replace("&amp;","&");
	
	return strResult;
};
//End Suggestion Class