/********************************************************************
* HTML ComboBox
* Copyright (C)2005 CS Wagner.
* This provides ComboBox functionality for HTML.
*********************************************************************
* HOWTO:
* You may use this on as many select elements as you want.
* For each select element, add the following three lines:
*   onfocus='javascript:combo_focus(this);'
*   onkeydown='javascript:combo_keydown(this,event);'
*   onkeypress='javascript:combo_keypress(this,event);'
* Also, make sure the first option is empty, as in:
*   <option value=''></option>
*********************************************************************
* HOW IT WORKS:
* This attempts to capture key presses and alter the value of the
* first option in the select list.  Doing so can be very complicated
* because every web browser seems to process key press events in a
* different way.
* Others have tried this and have hit common problems.  The ones that
* I know of have been handled:
* Backspace Problem:
*   When you hit backspace, you go to the previous web page.
*   I fixed this by cancelling the default backspace function.
* Auto-Selection of Options:
*   When you type the first letter of an option, the option is
*   selected automatically.
*   I fixed this by cancelling the default auto-select function.
* Edit of Existing Options:
*   Can user edit an option in the list?
*   When you edit while an option is selected, the edits replace the
*   first (editable) item in the list.
*********************************************************************
* COMPATABILITY:
* If the user does not have Javascript, this will not work.
* However, they will easily use the Select field with the values in
* the field.
* With Javascript, this works fine in Netscape/Mozilla browsers as
* well as IE browsers.
* In Opera, the backspace cannot be avoided and it will go to the
* previous page.
*********************************************************************
* TO-DO
* I save combo_typed separately because I want to work on a sort of
* cursor that will allow you to use the left and right cursor keys
* to move around in the text.  However, there are problems with that
* whole idea - mainly, the fact that there's no visible cursor in
* a select field.
*********************************************************************/

var combo_typed = ""; // Ensure the typed string is not lost.

/**
* When the select is focused, set the vlaue of combo_typed.
*/
function combo_focus(select)
{
	combo_typed = select.options[0].value;
}

/**
* Capture and ignore key events that we don't want.
* By default, pressing the first letter of an option will
* jump to that option, we don't want it to jump around.
* Also, IE processed backspace on keydown.
*/
function combo_keydown(select, event)
{
	// Pull the window's event if it exists.
	if(window.event) event = window.event;

	// Get the key pressed.
	var c = 0;
	if(event.which) c = event.which;
	else if(event.keyCode) c = event.keyCode;

	// Block backspace on IE's keydown event.
	if(c == 8 || c == 127)
		if(event.keyCode) event.keyCode = 0;

	// Block auto-select on Mozilla/Netscape's keydown event.
	if(c >= 32 && c <= 126) // All letters/numbers/punctuation
		if(event.preventDefault) event.preventDefault();

	return false;
}

/**
* Handle key presses.
*/
function combo_keypress(select, event)
{
	// Pull the window's event if it exists.
	if(window.event) event = window.event;

	// Fix IE events to handle preventDefault
	combo_fixEvent(event);

	// Which option is selected?
	// We handle the 0th item differently than the others.
	var selected = select.selectedIndex;
	
	// Get the key pressed.
	var c = 0;
	if(event.which) c = event.which;
	else if(event.keyCode) c = event.keyCode;
	if(c >= 32 && c <= 126) // All letters/numbers/punctuation
		event.preventDefault();
	
	// The 0th item (the editable one) is selected.
	if(selected == 0)
	{
		if(c == 8 || c == 127) // Backspace
		{
			event.preventDefault(); // Prevent back-button navigation
			if(combo_typed.length > 0)
				combo_typed = combo_typed.substring(0, combo_typed.length - 1);
			else
				combo_typed = "";
			select.options[0] = new Option(combo_typed, combo_typed);
		}
		else if(c >= 32) // Add the character to the string
		{
			if(event.returnValue) event.returnValue = false; // Prevent IE from auto-selecting
			combo_typed += String.fromCharCode(c);
			select.options[0] = new Option(combo_typed, combo_typed);
		}
	}
	// One of the non-editable items is selected.
	else
	{
		if(c == 8 || c == 127) // Backspace
		{
			event.preventDefault(); // Prevent back-button navigation
			combo_typed = select.options[selected].value;
			if(combo_typed.length > 0)
				combo_typed = combo_typed.substring(0, combo_typed.length - 1);
			else
				combo_typed = "";
			select.options[0] = new Option(combo_typed, combo_typed);
			selected = 0;
		}
		else if(c >= 32) // Copy selected to item 0 and add the keypress to it.
		{
			if(event.returnValue) event.returnValue = false; // Prevent IE from auto-selecting
			combo_typed = select.options[selected].value;
			combo_typed += String.fromCharCode(c);
			select.options[0] = new Option(combo_typed, combo_typed);
			selected = 0;
		}
	}
	// Select the appropriate item.
	select.selectedIndex = selected;
	return false;
}

function combo_fixEvent(event)
{
	if(!event.stopPropagation)
	{
		event.stopPropagation = new Function('this.cancelBubble = true');
	}
	if (!event.preventDefault)
	{
		event.preventDefault = new Function('this.returnValue = false');
	}
}

