/*  
	Title : Semi Auto Suggest Box
*/

 /**
	* @argument SearchInputID - The id of the text input for the loop up.
	* @argument MultiSelectID - The id of the select tag for the results to be placed.
	* @argument fnSearch - The JavaScript function to call to get results, 
	*						this function will get passed a string value of the requested search text and
	*						must return an array of objects with the following members; id, text
	* @argument fnFound - The JavaScript function to call when a result is selected,
	*						this function will get passed the id and text of the selected object plus any extra arguments passed in
	*						when the results were created.
	*/
function SemiAutoSuggestBox(SearchInputID, MultiSelectID, fnSearch, fnFound, showIfZeroLength, SuggestBoxWidth) {
    
	var that = {}; // Must use 'that' so not to confuse with 'this' which is the global object.

	/* Private Variables 
	*
	* These variables can only be accessed by functions inside the scope of this object.
	*/
	var eSearchInput, eMultiSelect;
	var iMaxListHeight = 280;
	var arrArgs; 
	var iSelectTextHeight = 22; // You may need to change this depending on your CSS.
	var iTimeOutWait = 500;		// If your finding that your custom functions are taking to long up this variable by 500
	var TimeOut;
	var iLastKeyPressed;
	
    /* Private Functions 
	*
	* These functions can only be accessed by functions inside the scope of this object.
	*/

	function Initiate() {
		eSearchInput = document.getElementById(SearchInputID);
		eMultiSelect = document.getElementById(MultiSelectID);

		// Position the results area directly underneath the input box ready for deployment
		PositionElement();
		eMultiSelect.style.display = 'none';

		// Add events
		eMultiSelect.onclick = GetResultClickHandler;
		eMultiSelect.onkeypress = GetResultKeyPressHandler;
	}

	function GetResultClickHandler() {
	
		if (eMultiSelect.selectedIndex != -1)
		{
			var id = eMultiSelect.options[eMultiSelect.selectedIndex].id,
				text = eMultiSelect.options[eMultiSelect.selectedIndex].innerHTML;

			eSearchInput.value = text.replace(/&amp;/ig, '&');
			eMultiSelect.style.display = 'none';

			fnFound(id,text,arrArgs);
		}
	}

	function GetResultKeyPressHandler(evt) {
		evt = evt || event;
		iLastKeyPressed = evt.keyCode || evt.which;

		if (iLastKeyPressed == 13) {
			GetResultClickHandler();
		}
	}

	function PositionElement() {
		if (SuggestBoxWidth === undefined) {
			eMultiSelect.style.width = eSearchInput.offsetWidth + 'px';
		}
		else {
			eMultiSelect.style.width = SuggestBoxWidth + 'px';
		}
	}

	function GenerateResults() {

		// Check for additional arguments
		if (arguments != undefined) {
			arrArgs = arguments;
		}

		// Check for up/down key press
		if (iLastKeyPressed == 40) {
			if (eMultiSelect.style.display == '') {
				eMultiSelect.options.selectedIndex = 0;
				eMultiSelect.focus();
				return;
			}
		}
		if (iLastKeyPressed == 38) {
			if (eMultiSelect.style.display == '') {
				eMultiSelect.options.selectedIndex = eMultiSelect.options.length-1;
				eMultiSelect.focus();
				return;
			}
		}

		// Check for valid search criteria
		if (!showIfZeroLength && eSearchInput.value.length < 1) {
			eMultiSelect.style.display = 'none';
			return;
		}

		// Get results
		var arrResults = fnSearch(eSearchInput.value,arrArgs), i, eOption, iCount = 0;
		
		if (arrResults == undefined) {
			eMultiSelect.style.display = 'none';
			return;
		}

		eMultiSelect.innerHTML = ''; 

		for (i=0; i < arrResults.length; i++) {
			if (arrResults[i] != undefined) {

				eOption = document.createElement('option');
				eOption.setAttribute('id',arrResults[i].id);
				eOption.innerHTML = arrResults[i].text;

				eMultiSelect.appendChild(eOption);

				iCount++;
			}
		}

		if (iCount < 1) {
			eMultiSelect.style.display = 'none';
			return; // No results found.
		}

		PositionElement();
		var iHeight = iCount*iSelectTextHeight; 

		if (iCount > 2) {
			if (iHeight > iMaxListHeight) { // Don't want it to tall on the page
				eMultiSelect.style.height = iMaxListHeight+'px';
			}
			else {
				eMultiSelect.style.height = iHeight+'px';
			}
		}

		eMultiSelect.style.display = '';
	}

	/* Public Variables 
	*
	* These variables are available from the returning object that this constructor creates,
	* new public variables can be added to the returning object at any time.
	*/
	var undefined;

	/* Public Functions 
	*
	* These functions are available from the returning object that this constructor creates,
	* new public functions can be added to the returning object at any time.
	*/

	that.CreateResults = function(evt) {
		evt = evt || event;
		iLastKeyPressed = evt.keyCode || evt.which;
		
		if (iLastKeyPressed === 40 || iLastKeyPressed === 38) {
			GenerateResults();
		}
		else {
			if (TimeOut !== undefined) {
				TimeOut = window.clearTimeout(TimeOut);
			}

			TimeOut = window.setTimeout(GenerateResults, iTimeOutWait);
		}
	}

	Initiate(); // Do all setup when the object is created.

	/* 
	* This (or that) is the object returned with all public members and
	* functions included above when the contructor is instantiated.
	*/
    return that;
}
