//<script>
var arrGlossary = new Array();
var oRegTags = new RegExp();
oRegTags.compile("(^\\[)|(\\]$)", "g");

//glossary object
function GlossaryObject(arr, div, bQuote, left, top, width, height)
{
	try{
		this.entryID = 0;
		this.entryCount = 0;
		this.arr = arr;
		this.str = "";
		this.div = div;
		this.quote = bQuote;
		this.left = left;
		this.top = top;
		this.width = width;
		this.height = height;
		this.ispopup = (div.tagName == null);
		this.isopen = false;
		return this;
	}catch(e){getError(e);}
}

//Utilities:
//get event element 
function getEventElement(evt)
{
	try{
		evt = getEvent(evt);
		var oElement = evt.target;
		return oElement;
	}catch(e){getError(e);}
}

function getDivDoc(o)
{
	return (o.document == null) ? document : o.document;
}

//check if there is empty string
function isEmpty(str)
{
	try{
		str = str.replace(/^\s+/g,"").replace(/\s+$/g,"");
		if (str.match(/\S/) && str.length > 2)
			return false;
		return true;	
	}catch(e){getError(e);}
}
//get entry id
function getEntryId(sElementID, iEntryID)
{
	try{
		return ("div" + sElementID + "_e" + iEntryID);
	}catch(e){getError(e);}
}
//get error message
function getError(e)
{
	//alert(e.description);
}

//Events :
//onblur event
function onBlurEvent(evt)
{
	try{
		var oElement = getEventElement(evt);
		
		if(oElement.getAttribute("mode") == "off")
			return;
		var o = arrGlossary[oElement.id];		
		var oDiv = o.div;
		if(o.ispopup)
			oDiv = oDiv.getElementsByTagName("div")[0];
		if(this.id == oDiv.id)
			oElement.focus();
		else
			hideGlossary(o);
	}catch(e){getError(e);}
}
//onpaste event
function onPasteEvent(evt)
{
	try{
		evt = getEvent(evt);
		var oElement = evt.target;
		if(oElement.getAttribute("mode") == "off")
			return;	
		oElement.value = window.clipboardData.getData("Text");
		evt.stopPropagation();
		evt.preventDefault();
		onKeyupEvent(evt);
	}catch(e){getError(e);}
}
//onkeyup event
function onKeyupEvent(evt)
{
	try{
		var oElement = getEventElement(evt);
		if(oElement.getAttribute("mode") == "off")
			return;		
		var keyCode = evt.keyCode;
		arrGlossary[oElement.id].str = oElement.value;
		if (keyCode==32 || keyCode==189 || keyCode==8 || keyCode==16 || keyCode==46 || keyCode==45 || keyCode==188 || keyCode==186 || keyCode==190 || (keyCode>=48 && keyCode<=57) || (keyCode>=65 && keyCode<=90))
		{	
			cleanGlossary(oElement); 
			var o =  arrGlossary[oElement.id];
			if (isEmpty(o.str))
				hideGlossary(o);
			else
				fillGlossary(oElement);
		}
		if (keyCode == 38 || keyCode == 40) //up or down key
			arrowKeys(oElement,keyCode);
	}catch(e){getError(e);}
}
//onfocus event --> show the glossary div if there is a value in the input
function onFocusEvent(evt)
{
	try{
		var oElement = getEventElement(evt);
		if(oElement.getAttribute("mode") == "off")
			return;		
		var o = arrGlossary[oElement.id];
		var iEntryCount = o.entryCount;
	
		if (!isEmpty(oElement.value) && iEntryCount > 0)
			displayGlossary(o);
	}catch(e){getError(e);}
}
//onkeydown event --> keyboard handler
function onKeydownEvent(evt)
{
	try{
		evt = getEvent(evt);
		var oElement = evt.target;
		if(oElement.getAttribute("mode") == "off")
			return;
		var o = arrGlossary[oElement.id];
		var oDiv = o.div;
		var keyCode = evt.keyCode;
		var iEntryID = o.entryID;
		switch(keyCode)
		{
			case 27 ://esc
				hideGlossary(o);
				evt.stopPropagation();
				evt.preventDefault();
				return false;
				break;
			case 9: //tab
			case 13 ://enter
				if (isDisplay(o))
				{
					if(iEntryID != 0)
					{
						evt.stopPropagation();
						evt.preventDefault();
						onEntryClick(oElement);
					}
					else// When enter is pressed and nothing is checked run search.
						hideGlossary(o);
					return false;
				}
				break;
		}
	}catch(e){getError(e);}
}

//onMouseDown Event on entry:
function onEntryClick(oElement)
{
	try{	
		
		var o = arrGlossary[oElement.id];
		var sEntryID = getEntryId(oElement.id, o.entryID)  
		var oEntry = getDivDoc(o.div).getElementById(sEntryID);
		if (oEntry != null)
		{
			//var s = oEntry.innerText;
			var s = oEntry.innerHTML.replace(/<[^>]+>/g,"")
			s = s.replace(/&nbsp;/g, " ");
			if (o.quote)
				s = "[" + s + "]";
			oElement.value = s.replace(/&gt;/g, ">");
		}			
		hideGlossary(o);
	}catch(e){getError(e);}
}
// keyboard arrow keys handlers
function arrowKeys(oElement, iKeyCode)
{
	try{
		var o = arrGlossary[oElement.id];
		var oDiv = o.div;
		var iEntryCount = o.entryCount;

		if ((!isDisplay(o)) || iEntryCount == 0) 
			return;

		var sID =o.entryID; 

		switch(iKeyCode)
		{
			case 38 : //arrow up	
				if (sID - 1 <= 0)
					sID = iEntryCount + 1;
				(--sID);
				break;
			case 40 : //arrow down
				if (sID + 1 > iEntryCount) 
					sID = 0;
				(++sID);
				break;
		}
	
		var sEntryID = getEntryId(oElement.id, sID);
		var oEntry = getDivDoc(oDiv).getElementById(sEntryID);
		setHoverGlossary(true, oEntry);

		scrollIntoViewGlossary(o, oEntry);
	}catch(e){getError(e);}
}

//scrollintoview
function scrollIntoViewGlossary(o, oEntry)
{
	try{
		var oDiv = (o.ispopup) ? o.div.document.getElementsByTagName("div")[0] : o.div;			
		var iEntryOffsetTop =  oEntry.offsetTop;
		var iEntryOffsetHeight =  oEntry.offsetHeight;
		var iScrollTop = oDiv.scrollTop;
		var iHeight = oDiv.offsetHeight - iEntryOffsetHeight + iScrollTop;	
		if(iEntryOffsetTop < iScrollTop)
			oEntry.scrollIntoView(true);
		else if (iEntryOffsetTop > iHeight)
			oEntry.scrollIntoView(false);
	}catch(e){getError(e);}
}
//onmouseover Event
function setHoverGlossary(bOn, oElement)
{
	try{
		if (!oElement) return;
		var sID = oElement.id.replace(/^div(.+)_e\d+$/i,"$1")
		var iEntryID = arrGlossary[sID].entryID;
		var oDiv = arrGlossary[sID].div; 	
		if (iEntryID > 0)
		{
			getDivDoc(oDiv).getElementById(oElement.id.replace(/_e\d+$/i, "_e" + iEntryID)).style.backgroundColor = "White";
			arrGlossary[sID].entryID = 0;
		}

		if (bOn)
		{
			if((/_e(\d+)$/i).exec(oElement.id))
				arrGlossary[sID].entryID = Number(RegExp.$1);
			
			oElement.style.backgroundColor = "Silver"; 
			oElement.style.cursor = "pointer"; 
		}
	}catch(e){getError(e);}
}

//Div glossary function
//hide glossary
function hideGlossary(o)
{
	try{
		if(o.ispopup)
			o.div.hide();
		else
			o.div.style.display = "none";
		o.isopen = false;
	}catch(e){getError(e);}
}

//display glossary
function displayGlossary(o)
{
	try{
		if(o.ispopup)
			o.div.show(o.left, o.top, o.width, o.height); 
		else
			o.div.style.display = "inline";
		o.isopen = true;
	}catch(e){getError(e);}
}

function isDisplay(o)
{
	try{
		return o.isopen;
	}catch(e){getError(e);}
}
//clean glossary
function cleanGlossary(oElement)
{
	try{
		var o = arrGlossary[oElement.id];
		var oDiv = (o.ispopup) ? o.div.document.getElementsByTagName("div")[0] : o.div;			
		oDiv.innerHTML = "";

		arrGlossary[oElement.id].entryCount = 0;
		arrGlossary[oElement.id].entryID = 0;
	}catch(e){getError(e);}
}

function createEntry(oDiv, oElement)
{
	var oEntry = getDivDoc(oDiv).createElement("div");
	oEntry.style.backgroundColor = "white"; 
	oEntry.align = "right";
	if (!oEntry.addEventListener)
		oEntry.attachEvent("onmousedown",function(){onEntryClick(oElement)});
	return oEntry;
}

//fill glossary
function fillGlossary(oElement) 
{
	try{
		var id = oElement.id;
		var o = arrGlossary[id];
		var sValue = oElement.value.replace(oRegTags,"");
		if (isEmpty(sValue))
		{
			hideGlossary(o);
			cleanGlossary(oElement);
			return;
		}
		var oReg = new RegExp();
		sValue = sValue.replace(/\?|\!|\*|\.|\/|\\|\-|\(|\)|\[|\]/g,"\\$&");
		oReg.compile(sValue, "i");
		var arr = o.arr;
		var n = arr.length, text;
		var oEntry = createEntry(o.div, oElement);
		var oDiv = (o.ispopup) ? o.div.document.getElementsByTagName("div")[0] : o.div;
		for (var i = 0; i < n; i++)
		{
			text = arr[i];
			if (oReg.test(text))
			{
				addEntry(o, oDiv, id, text.replace(sValue, '<b>' + sValue + '</b>'), oEntry, oElement);
				if (o.entryCount > 50)
					break;
			}
		}
		if (o.entryCount > 0)
			displayGlossary(o);
		else
			hideGlossary(o);
	}catch(e){getError(e);}
}

//add entry to the glossary
function addEntry(o, oDiv, id, text, oEntry, oElement)
{
	try{
		oEntry = oEntry.cloneNode(true);
		oEntry.innerHTML = text;
		oEntry.id = getEntryId(id, ++o.entryCount);
		if (oEntry.addEventListener)
		{
			oEntry.addEventListener("mouseover",function(){setHoverGlossary(true,oEntry)}, true);
			oEntry.addEventListener("mouseout",function(){setHoverGlossary(false,oEntry)}, true);
			oEntry.addEventListener("mousedown",function(){onEntryClick(oElement)}, true);
		}
		else
		{
			oEntry.attachEvent("onmouseover",function(){setHoverGlossary(true, oEntry)});
			oEntry.attachEvent("onmouseout",function(){setHoverGlossary(false, oEntry)});
		}

		oDiv.appendChild(oEntry);
	}catch(e){getError(e);}
}