/********************************************************************
* Auto-Complete Text Field
* @author CS Wagner <chris@kainaw.com>
* @version 1.0
*********************************************************************
* Provides functionality to a standard HTML text field to
* auto-complete a preset array of values while still allowing custom
* values.
* If the web browser does not support the functions used to detect
* and move the cursor as needed, the text field will operate as a
* normal text field without auto-complete ability.
*********************************************************************
* METHOD:
* On a KEYDOWN event (before the field has the new character added)
* the old value is set.
* On a KEYUP event (after the field has the new character added), if
* the new field value is longer than the old field value, the
* substring before the cursor is compared to the list of possible
* auto-complete values. If one of the auto-complete values matches,
* the field.value is set to the auto-complete value.
* NOTE:
* For speed, this script will stop on the first match.  Therefore,
* it works best if the values are in alphabetical order.  If they
* are not, it may be difficult to get it to match values that are not
* in order.
*********************************************************************
* USE:
* Inside of the INPUT tag of type 'text' add a call to autocomplete
* triggered by ONKEYUP.
* EXAMPLE:
* <INPUT TYPE="text"
*  ONKEYDOWN="javascript:setOldValue(this)"
*  ONKEYUP="javascript:autoComplete(this, new
*           Array('Value1','Value2','Another Value'))">
*********************************************************************/

var autoComplete_oldValue; // Holds the value before character entry

/**
 * Sets the old value.
 * @param field	the field to get a value from
 **/
function setOldValue(field)
{
	autoComplete_oldValue=field.value;
}

/**
 * If the text before the cursor matches a value in the given list,
 * this will auto-complete the rest of the text value without changing
 * the cursor position.
 * @param field	the field to auto-complete
 * @param vals	an array of values for auto-completion
 **/
function autoComplete(field, vals)
{
	// Break out of this function if the field is empty
	// or the new value isn't longer than the old value.
	if(field.value.length==0) return;
	if(field.value.length<=autoComplete_oldValue.length) return;

	var position=getCursorPosition(field);
	if(position==0) return; // Don't do anything when cursor is at position 0

	var value=field.value; // A working value that we can change
	var frontValue=value.substring(0,position); // Text before the cursor
	var fillValue=""; // Working string that will hold the auto-complete fill value

	// Cycle through all the vals to find a match
	for(var i=0; i<vals.length; i++)
	{
		if(frontValue.length<vals[i].length) // Don't check small values
		{
			fillValue=vals[i].substring(0,frontValue.length); // Starting text of vals[i]
			if(fillValue.toUpperCase()==frontValue.toUpperCase()) // Case insensitive compare
			{
				fillValue=vals[i]; // vals[i] is the auto-complete value
				i=vals.length; // Break out of this for loop
			}
			else fillValue=""; // vals[i] is no good, doesn't match
		}
		else fillValue=""; // vals[i] is no good, too short
	}

	if(fillValue.length>0) // An empty string means no value was found
	{
		value=fillValue;
	}
	else // No value was found, use the frontValue instead
	{
		value=frontValue;
	}

	if(field.value!=value) // Only update the field if the new value has changed
	{
		field.value=value; // This moves the cursor to the end
		setCursorPosition(field,position); // Put the cursor back where it goes
	}
}

/**
 * Gets the position of the cursor in a text field.
 * A zero is returned if this function is not supported.
 * @param field	The text field containing the cursor
 * @return position of the cursor
 **/
function getCursorPosition(field)
{
	var position=0; // Default value

	if(field.selectionStart) // Netscape & Mozilla variants
	{
		position=field.selectionStart;
	}

	else if(document.selection && document.selection.createRange) // IE variants
	{
		var original=field.value; // Save the old text
		field.caretPos=document.selection.createRange();
		field.caretPos.text="~"; // A character that will NOT be in the text
		position=field.value.search("~");
		field.value=original; // This moves the cursor to the end
		setCursorPosition(field, position) // Put the cursor back
	}

	return position;
}

/**
 * Moves the cursor of a text field to a specified position.
 * @param field	The text field containing the cursor
 * @param position	Position to move the cursor to
 **/
function setCursorPosition(field, position)
{
	// Validity checks
	if(position<0) position=0;
	if(position>field.value.length) position=field.value.length;

	if(field.selectionStart) // Netscape and Mozilla variants
	{
		field.selectionStart=position;
		field.selectionEnd=position;
	}

	else if(field.createTextRange) // IE variants
	{
		var range=field.createTextRange();
		range.collapse(true);
		range.moveEnd('character', position);
		range.moveStart('character', position);
		range.select();
	}
}

