/**
 * ComboBox3
 *
 * Version 0.95
 * Last Change: 2005-06-30
 *
 *(c) 2005 S.Wiegmann <stefan@impulse030.de>
 * Project-Page: http://www.impulse030.de/projects/comboBox3/
 *
 * inspired by Jared Nuzzolillo's ComboBox
 * http://webfx.eae.net/dhtml/combobox/combobox.htm
 *
 * Licensed under the terms of the GNU Lesser General Public License:
 * http://www.opensource.org/licenses/lgpl-license.php
 *
 *
 * Usage:
 * There are two ways to create a new comboBox:
 * 1.	If you simply want to add comboBox(es), add the following code to your BODY-onload:
 *			comboBox3('selectFieldName' [, widthPx]);
 *
 * 2.	If you want to add comboBox(es) and you need the Object-Name(s) later,
 *		add the following code to your BODY-onload:
 *			myObj=new comboBox3Obj('myObj', 'selectFieldName' [, widthPx]);
 *
 * In both cases the 'widthPx'-Argument is optional. If not specified, the width of the
 * original SELECT-Field is taken
 */


var comboBoxKeyCode;
var comboBoxes = new Array();


function comboBox3(fieldName)
{
	/**
	 * Creates a new comboBox (Object) within the Array 'comboBoxes'
	 *
	 * Arguments:
	 * fieldName			= (str)	The Name of your SELECT-Field
	 * [optional] width		= (int)	The Width in Pixel,
	 *								if not specified, the Width of the original SELECT-Field is taken
	 */

	newBoxObjId	= comboBoxes.length + 1;	

	if (arguments[1])
	{
		newObjWidth = arguments[1];
	}
	else
	{
		newObjWidth = null;
	}

	newBoxObjName	= 'comboBoxes[' + newBoxObjId + ']';
	
   comboBoxes[newBoxObjId] = new comboBox3Obj(newBoxObjName, fieldName, newObjWidth);
}


function comboBox3Obj(objName, fieldName)
{
	// Does the SELECT-Field exist ?
	if (!document.getElementsByName(fieldName)[0])
	{
		return false;
	}


	// Detect Useragent
	var agt		= navigator.userAgent.toLowerCase();
	var isIE	= (agt.indexOf("msie") != -1 && agt.indexOf("opera") == -1);
	var isOpera	= (agt.indexOf("opera") != -1);
  	var isSafari = (agt.indexOf("safari") != -1);


	// Removed Support for Opera / 2005-06-28
	// (There is a Scrolling-Bug in Opera with dynamic added Options)
	if (isOpera || isSafari)
	{
		return false;
	}
	

	// Basic Setup
	this.objName	= objName;
	this.fieldName	= fieldName;
	this.fieldObj	= document.getElementsByName(this.fieldName)[0];
	this.value		= this.fieldObj.options[this.fieldObj.options.selectedIndex].text; // Current ComboBox-Value

	// Determine ComboBox-Width, set to default if not specified 
	if (arguments[2])
	{
		this.width = parseInt(arguments[2]);	
	}
	else if (this.fieldObj.style.width)
	{
		this.width = parseInt(this.fieldObj.style.width);
	}
	else if (this.fieldObj.width)
	{
		this.width = parseInt(this.fieldObj.width);
	}
	else if (this.fieldObj.offsetWidth)
	{
		this.width = this.fieldObj.offsetWidth;
	}
	else
	{
		this.width = '200';
	}


	// Is there a onChange-Event on the original Select-Field ?
	if (this.fieldObj.onchange == null)
	{
		this.onChangeFunction = String(null);
	}
	else
	{
		tmpStr = String(this.fieldObj.onchange);
		this.onChangeFunction = tmpStr.substr(tmpStr.indexOf('{')+2, tmpStr.lastIndexOf('}')-tmpStr.indexOf('{')-3);
	}


	// Hide original Form-Object
	this.fieldObj.style.display	= 'none';
	

	// Define & add Main-Object
	this.obj				= document.createElement('DIV');
	this.obj.id				= this.fieldName + 'ComboBox';
	this.obj.className		= 'comboBox';
	this.obj.style.display	= 'inline';

	this.fieldObj.parentNode.insertBefore(this.obj, this.fieldObj);


	// Define & Add List-Object	
	this.list					= document.createElement('SELECT');
	this.list.size				= 8;
	this.list.className			= 'list';
	this.list.style.position	= 'absolute';
	this.list.style.width		= this.width + 'px';
	this.list.onchange			= new Function ("", this.objName + ".select();" + this.onChangeFunction);
	this.list.onclick			= new Function ("", this.objName + ".select(true);" + this.onChangeFunction);
	this.list.style.display		= 'none';

	this.obj.appendChild(this.list);
	

	// Define & add the Text-Field
	this.txtField				= document.createElement("INPUT");
	this.txtField.name			= '_' + this.fieldName + '_';
	this.txtField.type			= "text";
	this.txtField.className		= "text";
	//this.txtField.style.margin	= '0px';
	//this.txtField.style.padding	= '0px';
	this.txtField.value			= this.value;
	//this.txtField.onfocus		= new Function ("", this.objName + ".closeList()");
	this.txtField.onclick		= new Function ("", this.objName + ".clearText()");
	this.txtField.onkeydown		= comboBoxCaptureKey;
	this.txtField.onkeyup		= new Function ("", this.objName + ".txtFieldKey(); " + this.onChangeFunction);

	this.obj.appendChild(this.txtField);


	// Define & add the Toggle-Button
/*	if (isIE) // For Internet Explorer we got a special Arrow-Button
	{
		this.toggleButton			= document.createElement("BUTTON");
		this.toggleButton.className	= "toggleButtonIE";

		tmpObj = document.createElement('P');
		tmpObj.appendChild(document.createTextNode('6'));

		this.toggleButton.appendChild(tmpObj);
	}
	else
	{*/
		this.toggleButton			= document.createElement("INPUT");
		this.toggleButton.className	= "toggleButton";	
		this.toggleButton.type		= "button";
	    this.toggleButton.value		= '';
//	}

	this.toggleButton.onfocus		= new Function ("", "this.blur();");
	this.toggleButton.onclick		= new Function ("", "this.blur(); " + this.objName + ".toggleList();");
	//this.toggleButton.style.width	= '17px';	
	//this.toggleButton.style.margin	= '0px';
	//this.toggleButton.style.padding	= '0px';	
	//this.toggleButton.style.height	= this.txtField.offsetHeight + 'px';

	// Add it
	this.obj.appendChild(this.toggleButton);
	
  return false;
	// Finish Setup
	// (Some values can only be set at the end)

	//this.txtField.style.width	= this.width - this.toggleButton.offsetWidth + 'px';

	// Get & Set List-Position
    var tmpObj = this.txtField;
    var tmpPosX = 0;
	var tmpPosY	= 0;
    
    while(tmpObj.tagName != "BODY")
	{
        tmpPosX		+= tmpObj.offsetLeft;
        tmpPosY		+= tmpObj.offsetTop;
        tmpObj		= tmpObj.offsetParent;        
    }

	this.list.style.left	= tmpPosX;
	this.list.style.top		= tmpPosY + this.txtField.offsetHeight;
}


comboBox3Obj.prototype.buildList = function()
{
	/**
	 * Arguments:
	 * 1: new Value (String) (Provide empty String if current Text-Field Value shall be taken)
	 * 2: Display/Hide (bool) true / False
	 */

	var value, tmpText, tmpObj;


	if (arguments.length > 1 && !arguments[1])
	{
		this.list.style.display = 'none';
		
		return true;
	}


	if (arguments.length && arguments[0] !== null)
	{
		value = arguments[0];
	}
	else
	{
		value = this.txtField.value.toLowerCase();
	}


	valueLower			= value.toLowerCase();
	valueLength			= value.length;
	txtFieldValueLower	= this.txtField.value.toLowerCase();
	tmpLength			= this.fieldObj.length;
	optI				= 0; // Counter

	for (i=1; i<tmpLength; i++)
	{
		tmpText = this.fieldObj.options[i].text.toLowerCase();

		if (valueLower == tmpText.substr(0, valueLength))
		{
			if (this.list.options[optI])
			{
				this.list.options[optI].value		= this.fieldObj.options[i].value;
				this.list.options[optI].text		= this.fieldObj.options[i].text;
				this.list.options[optI].selected	= (txtFieldValueLower == tmpText);
			}
			else
			{
				this.list.options[optI] = new Option(
					this.fieldObj.options[i].text,
					this.fieldObj.options[i].value,
					false,
					txtFieldValueLower == tmpText
				);
			}
		
			optI++;				
		}
	}

	this.list.options.length	= optI;
	this.list.style.display		= optI ? '' : 'none';
}


comboBox3Obj.prototype.toggleList = function()
{
	if (this.list.style.display == 'none')
	{
		this.buildList('', true);
		this.focusList();
	}
	else
	{
		this.closeList();
	}
}


comboBox3Obj.prototype.closeList = function()
{
	if (this.list.style.display !== 'none')
	{
		this.list.style.display = 'none';
	}
	this.txtField.focus();
}

comboBox3Obj.prototype.clearText = function()
{
	this.txtField.value = "";
	this.txtField.focus();
}

comboBox3Obj.prototype.select = function(closeB)
{
	if (this.list.options.selectedIndex == -1)
	{
		return true;
	}
	
	this.txtField.value = this.list.options[this.list.options.selectedIndex].text;
	this.fieldObj.value = this.list.value;

	if (closeB)
	{
		this.closeList();
	}
}


comboBox3Obj.prototype.txtFieldKey = function()
{
	// (The Key-Code in the Variable 'comboBoxKeyCode' is set via a global Function)

	// Pressed Arrow-Down Key: Open the List, set Focus on it	
	if (comboBoxKeyCode == 40)
	{
		this.fieldObj.value = this.txtField.value;
		this.buildList(this.txtField.value.toLowerCase(), true);
		this.focusList();
		
		if (this.list.options[0])
		{
			this.list.options[0].selected = true;		
		}
		
		return;
	}

	// Search the Textfield-Value in the Options of the original List
	txtFieldValueLower	= this.txtField.value.toLowerCase();
	foundValue			= false;
	
	for (i=0; i<this.fieldObj.length; i++)
	{
		tmpText	= this.fieldObj.options[i].text;

		if (tmpText.toLowerCase() == txtFieldValueLower)
		{
			this.fieldObj.value = this.fieldObj.options[i].value;
			foundValue			= true;

			continue;
		}
	}
	
	if (!foundValue)
	{
		this.fieldObj.value = null;
	}

	this.buildList();
}


comboBox3Obj.prototype.focusList = function()
{
	if (!this.list.options.length || this.list.style.display !== '')
	{
		return;
	}

	this.list.focus();
}


// Key-Capturing Function

function comboBoxCaptureKey(keyEvent)
{
	if (!keyEvent)
	{
		keyEvent = window.event;
	}

	if (keyEvent.which)
	{
		comboBoxKeyCode = keyEvent.which;
	}
	else if (keyEvent.keyCode)
	{
		comboBoxKeyCode = keyEvent.keyCode;
	}
	else
	{
		comboBoxKeyCode = null;
	}
}