/*******************************************************

AutoSuggest - a javascript automatic text input completion component
Copyright (C) 2005 Joe Kepley, The Sling & Rock Design Group, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*******************************************************

Please send any useful modifications or improvements via 
email to joekepley at yahoo (dot) com

*******************************************************/

var as_focused = null;
var as_inputText = "";
var as_suggestions = new Array();
var as_highlighted = -1;
var as_timeout = null;

/********************************************************

********************************************************/
function as_getSuggestions(value,code)
{
	HTTPQuery(code+value,as_callback);
}

/********************************************************

********************************************************/
function as_callback(code, suggestions) {
	if (code==200 || code=="200") {
		eval ("as_suggestions = new Array("+suggestions+");");
		as_showSuggestions();
	}
	else {
		as_suggestions = new Array();
		as_hideDiv();
	}
}

/********************************************************

********************************************************/
function as_showSuggestions() {
	if (as_suggestions.length < 1) return;
	as_createDiv();
	as_positionDiv();
	as_showDiv();
}

/********************************************************
onkeydown event handler for the input elem.
Tab key = use the highlighted suggestion, if there is one.
Esc key = get rid of the autosuggest dropdown
Up/down arrows = Move the highlight up and down in the suggestions.
********************************************************/
function as_keydown(ev) {
	var key = as_getKeyCode(ev);
	switch(key)
	{
		case 13: // ENTER
		as_useSuggestion();
		return false;
		break;

		case 9: // TAB
		as_useSuggestion();
		break;

		case 27: // ESC
		as_hideDiv();
		break;

		case 38: // KEYUP
		if (as_highlighted > 0)
		{
			as_highlighted--;
		}
		as_changeHighlight();
		break;

		case 40: //KEYDOWN
		if (as_highlighted < (as_suggestions.length - 1))
		{
			as_highlighted++;
		}
		as_changeHighlight();
		break;
	}
}

function as_request() {
	as_timeout = null;
	var f = as_focused.getAttribute("autofill");
	var c = as_focused.getAttribute("autofillcode");
	try { eval(f +"('"+as_focused.value+"','"+ c +"');"); }
	catch (e) { as_suggestions = new Array(); }
}

/********************************************************
onkeyup handler for the elem
If the text is of sufficient length, and has been changed, 
then display a list of eligible suggestions.
********************************************************/
function as_keyup(ev) {
	var key = as_getKeyCode(ev);
	switch(key)
	{
	//The control keys were already handled by onkeydown, so do nothing.
	case 13: // ENTER
	case 9: // TAB
	case 27: // ESC
	case 38: // KEYUP
	case 40: // KEYDOWN
		return;
	default:
		if (as_focused.value != as_inputText && as_focused.value.length > 0)
		{
			as_inputText = as_focused.value;
			if (as_timeout != null) clearTimeout(as_timeout);
			as_timeout = setTimeout('as_request()', 200);
		}
		else
		{
			if (as_focused.value.length < 1) { clearTimeout(as_timeout); as_timeout = null; }
			as_hideDiv();
		}
	}
}

/********************************************************
Insert the highlighted suggestion into the input box, and 
remove the suggestion dropdown.
********************************************************/
function as_useSuggestion() {
	if (as_highlighted > -1)
	{
		as_focused.value = as_suggestions[as_highlighted];
		as_hideDiv();
		//It's impossible to cancel the Tab key's default behavior. 
		//So this undoes it by moving the focus back to our field right after
		//the event completes.
		setTimeout("document.getElementById('" + as_focused.id + "').focus()",0);
	}
};

/********************************************************
Display the dropdown. Pretty straightforward.
********************************************************/
function as_showDiv()
{
	if (document.getElementById("autosuggest")) document.getElementById("autosuggest").style.display = "block";
};

/********************************************************
Hide the dropdown and clear any highlight.
********************************************************/
function as_hideDiv()
{
	if (document.getElementById("autosuggest")) {
		document.getElementById("autosuggest").style.display = "none";
		as_highlighted = -1;
	}
};

/********************************************************
Modify the HTML in the dropdown to move the highlight.
********************************************************/
function as_changeHighlight()
{
	var div = document.getElementById("autosuggest");
	var lis = div.getElementsByTagName('LI');
	for (var i=0; i<lis.length; i++)
	{
		var li = lis[i];

		if (as_highlighted == i)
		{
			li.style.backgroundColor = "#0000ff";
			li.getElementsByTagName("A")[0].style.color = "#ffffff";
		}
		else
		{
			li.style.backgroundColor = "#ffffff";
			li.getElementsByTagName("A")[0].style.color = "#000000";
		}
	}
};

/********************************************************
Position the dropdown div below the input text field.
********************************************************/
function as_positionDiv()
{
	var el = as_focused;
	var x = 0;
	var y = el.offsetHeight;

	//Walk up the DOM and add up all of the offset positions.
	while (el.offsetParent && el.tagName.toUpperCase() != 'BODY')
	{
		x += el.offsetLeft;
		y += el.offsetTop;
		el = el.offsetParent;
	}

	x += el.offsetLeft;
	y += el.offsetTop;

	var div = document.getElementById("autosuggest");
	div.style.left = x + 'px';
	div.style.top = y + 'px';
};

/********************************************************
Build the HTML for the dropdown div
********************************************************/
function as_createDiv()
{
	var ul = document.createElement('ul');
	ul.style.padding = "0px";
	ul.style.margin = "0px";
	ul.style.listStyleType = "none";

	//Create an array of LI's for the words.
	for (i=0; i<as_suggestions.length; i++)
	{
		var word = as_suggestions[i];

		var li = document.createElement('li');
		li.style.padding = "0px 5px";
		var a = document.createElement('a');
		a.style.fontFamily = "Verdana, Geneva, Arial, Helvetica, sans-serif";
		a.style.fontSize = "11px";
		a.style.textDecoration = "none";
		a.style.color = "#000000";
		a.href="javascript:false";
		a.innerHTML = word;
		li.appendChild(a);

		if (as_highlighted == i)
		{
			li.className = "selected";
		}

		ul.appendChild(li);
	}

	var div = document.getElementById("autosuggest");
	if (div==null || div==undefined) {
		div = document.createElement("DIV");
		div.id = "autosuggest";
		div.style.display = "none";
		div.style.position = "absolute";
		div.style.backgroundColor = "#ffffff";
		div.style.borderColor = "#000000";
		div.style.borderWidth = "1px";
		div.style.borderStyle = "solid";
		div.style.padding = "0px";
		
		div.appendChild(document.createElement("BR"));
		document.body.appendChild(div);
	}

	div.replaceChild(ul,div.childNodes[0]);


	/********************************************************
	mouseover handler for the dropdown ul
	move the highlighted suggestion with the mouse
	********************************************************/
	ul.onmouseover = function(ev)
	{
		//Walk up from target until you find the LI.
		var target = as_getEventSource(ev);
		while (target.parentNode && target.tagName.toUpperCase() != 'LI')
		{
			target = target.parentNode;
		}
	
		var lis = document.getElementById("autosuggest").getElementsByTagName('LI');	

		for (i in lis)
		{
			var li = lis[i];
			if(li == target)
			{
				as_highlighted = i;
				break;
			}
		}
		as_changeHighlight();
	};

	/********************************************************
	click handler for the dropdown ul
	insert the clicked suggestion into the input
	********************************************************/
	ul.onclick = function(ev)
	{
		as_useSuggestion();
		as_hideDiv();
		as_cancelEvent(ev);
		return false;
	};
};

/********************************************************

********************************************************/
function as_setFocus() {
	as_focused = this;
	as_inputText = "";
}

/********************************************************
 The AutoSuggest class binds to a text input field
 and creates an automatic suggestion dropdown in the style
 of the "IntelliSense" and "AutoComplete" features of some
 desktop apps. 
 Parameters: 
 elem: A DOM element for an INPUT TYPE="text" form field
 suggestions: an array of strings to be used as suggestions
              when someone's typing.

 Example usage: 
 
 Please enter the name of a fruit.
 <input type="text" id="fruit" name="fruit" />
 <script language="Javascript">
 var fruits=new Array("apple","orange","grape","kiwi","cumquat","banana");
 new AutoSuggest(document.getElementById("fruit",fruits));
 </script>

*********************************************************/

function as_init() {
	//Find all of the INPUT tags
	var tags = document.getElementsByTagName('INPUT');
	var afform = "";
	for (var i=0; i<tags.length; i++)
	{
		var tag = tags[i];
		//If it's a text tag, attach an AutoSuggest object.
		if(tag.type && tag.type.toLowerCase() == "text")
		{
			var af = tag.getAttribute("autofill");
			if (af!="" && af!=null && af!=undefined) {
				var afform = tag.form;
				tag.setAttribute("autocomplete","off");
				tag.onkeydown = function(ev) { as_keydown(ev); };
				tag.onkeyup = function(ev) { as_keyup(ev); };
				tag.onkeypress = function(ev) { 
					if(ev) return !(ev && ev.keyCode == 13);
					else return !(window.event && window.event.keyCode == 13);
				};
				tag.onfocus = as_setFocus;
			}
		}
	}
	if (as_onload) as_onload();
}

/********************************************************
Helper function to determine the keycode pressed in a 
browser-independent manner.
********************************************************/
function as_getKeyCode(ev)
{
	if(ev)			//Moz
	{
		return ev.keyCode;
	}
	if(window.event)	//IE
	{
		return window.event.keyCode;
	}
};

/********************************************************
Helper function to determine the event source element in a 
browser-independent manner.
********************************************************/
function as_getEventSource(ev)
{
	if(ev)			//Moz
	{
		return ev.target;
	}

	if(window.event)	//IE
	{
		return window.event.srcElement;
	}
};

/********************************************************
Helper function to cancel an event in a 
browser-independent manner.
(Returning false helps too).
********************************************************/
function as_cancelEvent(ev)
{
	if(ev)			//Moz
	{
		ev.preventDefault();
		ev.stopPropagation();
	}
	if(window.event)	//IE
	{
		window.event.returnValue = false;
	}
}

as_onload = window.onload;
window.onload = as_init;
