// JavaScript document

/**
 * AutoCompleteDB class
 */
function AutoCompleteDB()
{
	this.aNames = new Array();
	this.metaChars = new Array('\\','|','(',')','[',']','{','}','^','$','*','+','?','.','-','!');
}

AutoCompleteDB.prototype.assignArray = function(aList)
{
	for (var i in aList)
	{
		this.aNames.push(aList[i].replace(/&quot;/g, '"'))
	}
}

AutoCompleteDB.prototype.getMatches = function(str, aList, maxSize)
{
	var ctr = 0;
	
	for (var i in this.aNames)
	{
		if (this.aNames[i].match( this._getSearchRegEx(str) ))
	//	if (this.aNames[i].toLowerCase().indexOf(str.toLowerCase())==0) /*looking for case insensitive matches */
		{
			aList.push(this.aNames[i]);
			ctr++;
		}
		if (ctr == (maxSize-1)) /* counter to limit no of matches to maxSize */
			break;
	}
}

AutoCompleteDB.prototype._getSearchRegEx = function(str)
{
	var reg_val = str;
	
	for (var i in this.metaChars)
	{
		var met_char = this.metaChars[i];
		var regex = new RegExp("\\"+met_char, "g");
		reg_val = reg_val.replace(regex, '\\'+met_char);
	}
	/* debug */
	// window.status = "reg_val: "+reg_val;
	
	reg_val = reg_val.replace(/[āa]/gi, '[āa]');
	reg_val = reg_val.replace(/[čc]/gi, '[čc]');
	reg_val = reg_val.replace(/[ēe]/gi, '[ēe]');
	reg_val = reg_val.replace(/[ģg]/gi, '[ģg]');
	reg_val = reg_val.replace(/[īi]/gi, '[īi]');
	reg_val = reg_val.replace(/[ķk]/gi, '[ķk]');
	reg_val = reg_val.replace(/[ļl]/gi, '[ļl]');
	reg_val = reg_val.replace(/[ņn]/gi, '[ņn]');
	reg_val = reg_val.replace(/[šs]/gi, '[šs]');
	reg_val = reg_val.replace(/[ūu]/gi, '[ūu]');
	reg_val = reg_val.replace(/[žz]/gi, '[žz]');
//	reg_val = reg_val.replace(/\"/gi, '[\"(&quot;)]');
	var regex = eval('/^'+reg_val+'/gi');
	return regex;
}

/**
 * AutoComplete class
 */
function AutoComplete(oText, aNames)
{
	this.debug = false;
	this.itemHeight = 20;
	this.maxRowsPerSuggest = 7;
	
	
	this.itemHeightUnit = 'px';
	
	this.origText = '';
	
	this.oText = oText;
	this.oText.setAttribute("AUTOCOMPLETE", "off");
	
	var divSuggest = document.createElement('div');
	with (divSuggest.style){
		position="absolute";
		height = (this.maxRowsPerSuggest * this.itemHeight) + this.itemHeightUnit;
		visibility="hidden";
		borderTop="1px solid #aaaaaa";
		borderLeft="1px solid #aaaaaa";
		borderBottom="1px solid #333333";
		borderRight="1px solid #333333";
		backgroundColor="#FFFFFF"; zIndex="3"; overflow="auto"; textAlign="left";
	}
	document.body.appendChild(divSuggest);
	this.oDiv = divSuggest;
	
	this.needIFrame = (navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') == -1);
	
	if (this.needIFrame)
	{
		var iframe = document.createElement('iframe');
		iframe.setAttribute("frameborder", "no");
		iframe.setAttribute("scrolling", "no");
		with (iframe.style){
			position="absolute"; zIndex="2";
			width="20px"; height="20px";
			visibility="hidden";
		}
		document.body.appendChild(iframe);
		this.iFrame = iframe;
	}
	
	this.maxSize = -1;
	this.cur = -1;
	this.curPos = 0;
	
	/*debug here */
	//alert(oText+","+this.oDiv);
	
	this.db = new AutoCompleteDB();
	this.db.assignArray(aNames);
	
	oText.onkeyup = this.keyUp;
	oText.onkeydown = this.keyDown;
	oText.onclick = this.click;
	oText.autoComplete = this;
	oText.onblur = this.hideSuggest;
}

AutoComplete.prototype.hideSuggest = function()
{
	this.autoComplete._processIFrame('hide');
	this.autoComplete.oDiv.style.visibility="hidden";
}

AutoComplete.prototype.selectText = function(iStart, iEnd)
{
	if (this.oText.createTextRange) /* For IE */
	{
		var oRange = this.oText.createTextRange();
		oRange.moveStart("character",iStart);
		oRange.moveEnd("character",iEnd-this.oText.value.length);
		oRange.select();
	}
	else if(this.oText.setSelectionRange) /* For Mozilla */
	{
		this.oText.setSelectionRange(iStart,iEnd);
	}
	this.oText.focus();
}

AutoComplete.prototype.textComplete = function(sFirstMatch)
{
	if (this.oText.createTextRange || this.oText.setSelectionRange)
	{
		var iStart = this.oText.value.length;
		this.oText.value = sFirstMatch;
		this.selectText(iStart, sFirstMatch.length);
	}
}
 
AutoComplete.prototype.moveDown = function()
{
	if (this.oDiv.childNodes.length > 0 && this.cur < (this.oDiv.childNodes.length - 1))
	{
		++this.cur;
		for (var i=0; i<this.oDiv.childNodes.length; i++)
		{
			if (i == this.cur)
			{
				this._setStyle(this.oDiv.childNodes[i].style, 'over');
				this.oText.value=this.oDiv.childNodes[i].innerHTML;
			}
			else
			{
				this._setStyle(this.oDiv.childNodes[i].style, 'out');
			}
		}
		
		var item_h = this.itemHeight;
		var cur_rows = Math.round(parseFloat(this.oDiv.style.height) / item_h);
		var suggest_h = cur_rows * item_h;
		var cur_offset_top = this.oDiv.childNodes[this.cur].offsetTop + ((navigator.appName.indexOf("Netscape") != -1) ? 1 : 0);
		
		if (cur_offset_top >= suggest_h){
			var cur_pos = 9999;
		}
		else {
			var cur_pos = this.cur;
		}
		
		if (this.debug)
		{
			var log_str = 'cur_offset_top: '+cur_offset_top + ', cur: '+this.cur + ', cur_rows: '+cur_rows + ', suggest_h: '+suggest_h
						+ ', cur_pos: '+cur_pos+', item_h: '+item_h;
			
			document.getElementById('log').innerHTML = log_str;
		}
					
		if (cur_offset_top >= suggest_h)
		{
			this.oDiv.scrollTop += item_h;
		}
		else {
			//window.status = 'no need';
		}
		
	/*	if (this.cur >= cur_rows){
			this.oDiv.scrollTop += this.itemHeight;
		}*/
	}
}

AutoComplete.prototype.moveUp = function()
{
	if (this.oDiv.childNodes.length > 0 && this.cur > 0)
	{
		--this.cur;
		for (var i=0; i<this.oDiv.childNodes.length; i++)
		{
			if (i == this.cur)
			{
				this._setStyle(this.oDiv.childNodes[i].style, 'over');
				this.oText.value=this.oDiv.childNodes[i].innerHTML;
			}
			else
			{
				this._setStyle(this.oDiv.childNodes[i].style, 'out');
			}
		}
		
		var item_h = this.itemHeight;
		var cur_rows = Math.round(parseFloat(this.oDiv.style.height) / item_h);
		var suggest_h = cur_rows * item_h;
		var cur_offset_top = this.oDiv.childNodes[this.cur].offsetTop + ((navigator.appName.indexOf("Netscape") != -1) ? 1 : 0);
		var cur_pos = (this.cur >= cur_rows-1) ? cur_rows-1 : this.cur;
		
		if (this.debug)
		{
			var log_str = 'cur_offset_top: '+cur_offset_top + ', cur: '+this.cur + ', cur_rows: '+cur_rows + ', suggest_h: '+suggest_h
							+ ', cur_pos: '+cur_pos+', item_h: '+item_h;
			
			document.getElementById('log').innerHTML = log_str;
		}
		
	//	window.status += ', suggest offsetHeight:' + (this.oDiv.childNodes.length-1-cur_rows);
		
		// if cur = 20 and 
		if (cur_offset_top > 0 && this.cur > 0)
		{
			this.oDiv.scrollTop -= item_h;
		}
	}
}

AutoComplete.prototype.keyDown = function(oEvent)
{
	oEvent = window.event || oEvent;
	iKeyCode = oEvent.keyCode;
	
	switch(iKeyCode)
	{
		case 38: // up arrow
				this.autoComplete.moveUp();
			break;
		case 40: // down arrow
				if (this.autoComplete.oDiv.style.visibility == "hidden"){
					this.autoComplete.onTextChange(false); /* without autocomplete */
				}
				else {
					this.autoComplete.moveDown();
				}
			break;
		case 13: // return key
				window.focus();
			break;
		case 27:
				this.autoComplete.oText.value = this.autoComplete.origText;
				this.autoComplete.oText.focus();
				this.autoComplete.oDiv.innerHTML = "";
				this.autoComplete.oDiv.style.visibility = "hidden";
				this.autoComplete._processIFrame('hide');
			break;
	}
}

AutoComplete.prototype.keyUp = function(oEvent)
{
	oEvent = oEvent || window.event;
	var iKeyCode = oEvent.keyCode;
	
	if (iKeyCode == 8 || iKeyCode == 46)
	{
		this.autoComplete.onTextChange(false); /* without autocomplete */
	}
	else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode <= 46) || (iKeyCode >= 112 && iKeyCode <= 123))
	{
		//ignore
	}
	else
	{
		this.autoComplete.onTextChange(true); /* with autocomplete */
	}
}

AutoComplete.prototype.click = function()
{
	//this.autoComplete.onTextChange(false); /* without autocomplete */
}

AutoComplete.prototype.calculateSuggestPosition = function() /* to calculate the appropriate poistion of the dropdown */
{
	var oNode = this.oText;
	var x=0, y=oNode.offsetHeight;
	
	while(oNode.offsetParent && oNode.offsetParent.tagName.toUpperCase() != 'BODY')
	{
		x += oNode.offsetLeft;
		y += oNode.offsetTop;
		oNode = oNode.offsetParent;
	}
	
	x += oNode.offsetLeft;
	y += oNode.offsetTop;
	
	this.oDiv.style.top=y+"px";
	this.oDiv.style.left=x+"px";
//	var borderWidth = (navigator.appName.indexOf("Netscape") != -1) ? 2 : 0;
//	this.oDiv.style.width = oNode.offsetWidth-borderWidth+'px';
}

AutoComplete.prototype.onTextChange = function(bTextComplete)
{
	var txt = this.oText.value;
	var oThis = this;
	this.cur = -1;
	
	if (txt.length > 0)
	{
		this.origText = txt;
		
		while (this.oDiv.hasChildNodes())
			this.oDiv.removeChild(this.oDiv.firstChild);
		
		var aStr = new Array();
		this.db.getMatches(txt, aStr, this.maxSize);
		if(!aStr.length) {this.hideSuggest; return;}
		if(bTextComplete) this.textComplete(aStr[0]);
		this.calculateSuggestPosition();
		
		for (var i in aStr)
		{
			var oNew = document.createElement('div');
			with (oNew.style){
				lineHeight = this.itemHeight + this.itemHeightUnit;
				paddingLeft="4px";
				paddingRight="4px";
			}
			this.oDiv.appendChild(oNew);
			oNew.onmouseover =
			oNew.onmouseout =
			oNew.onmousedown = function(oEvent)
			{
				oEvent = window.event || oEvent;
				oSrcDiv = oEvent.target || oEvent.srcElement;
				
				//debug :window.status=oEvent.type;
				if (oEvent.type=="mousedown")
				{
					oThis.oText.value=this.innerHTML;
				}
				else if(oEvent.type=="mouseover")
				{
					oThis._setStyle(this.style, 'over');
				}
				else if(oEvent.type=="mouseout")
				{
					oThis._setStyle(this.style, 'out');
				}
				else
				{
					this.oText.focus();
				}
			}
			oNew.innerHTML = aStr[i];
		}
		
		if (this.oDiv.offsetWidth+3 < this.oText.offsetWidth)
		{
			this.oDiv.style.width = this.oText.offsetWidth+3+'px';
		}
		
		var plusBorder = this.needIFrame ? 2 : 0;
		if (aStr.length < this.maxRowsPerSuggest){
			this.oDiv.style.height = (aStr.length * this.itemHeight) + plusBorder + this.itemHeightUnit;
		}
		else {
			this.oDiv.style.height = (this.maxRowsPerSuggest * this.itemHeight) + plusBorder + this.itemHeightUnit;
		}
		
		this.oDiv.style.visibility = "visible";
		this._processIFrame('show');
	}
	else
	{
		this.oDiv.innerHTML = "";
		this.oDiv.style.visibility = "hidden";
		this._processIFrame('hide');
	}
}

/**
 * @access private
 */
AutoComplete.prototype._setStyle = function(oStyle, mode)
{
	if (mode == 'over')
	{
		with (oStyle){
			color="#ffffff";
			backgroundColor="highlight";
		}
	}
	else if (mode == 'out')
	{
		with (oStyle){
			color="#000000";
			backgroundColor="#ffffff";
			cursor="pointer";
			textAlign="left";
		}
	}
}

/**
 * @access private
 */
AutoComplete.prototype._processIFrame = function(action)
{
	if (this.needIFrame)
	{
		if (action == 'show')
		{
			with (this.iFrame.style)
			{
				visibility = "visible";
				top = this.oDiv.style.top;
				left = this.oDiv.style.left;
				width = this.oDiv.offsetWidth;
				height = this.oDiv.offsetHeight;
			}
		}
		else if (action == 'hide')
		{
			this.iFrame.style.visibility = "hidden";
		}
	}
}
