//
// Autosuggest class
//

function autosuggest (textbox, table, field, script)
{
	var url = null;
	var request = null;
	var suggestbox = null;
	var userText = null;
	var suggest_arr = null;
	var timeoutId = null;
	var withTypeAhead = false;
	var current = -1;
	var defaultScript = '../includes/suggestions.php';

	init();

	// function init
	function init ()
	{
		userText = textbox.value;

	    // assign the onkeyup event handler
	    textbox.onkeyup = function (event)
	    {
	        if (!event)
	        {
	            event = window.event;
	        }
	        handleKeyUp(event);
	    };

	    // assign onkeydown event handler
	    textbox.onkeydown = function (event)
	    {
	        if (!event)
	        {
	            event = window.event;
	        }
	        handleKeyDown(event);
	    };

	    // assign onblur event handler (hides suggestions)
	    textbox.onblur = function ()
	    {
	        hideSuggestions();
	    };

	    if(!script)
	    {
	    	script = defaultScript
	    }

	    // create the suggestions text box and request suggestions
	    createDropDown();
	    requestSuggestions(withTypeAhead);
	}

	// function requestSuggestions
	function requestSuggestions (useTypeAhead)
	{
		if(userText.length == 0)
		{
			hideSuggestions();
		}
		else
		{
			request = createRequest();

			if (request.readyState == 4 || request.readyState == 0)
			{
				if(!script) script = defaultScript;
				url = script + '?table=' + table + '&field=' + field + '&string=' + userText;
				request.open('GET', url, true);
		   		request.onreadystatechange = function ()
		   		{
		   			if (request.readyState == 4)
		   			{
		   				response = request.responseText;
		   				if(response.length > 0)
		   				{
							suggest_arr = response.split('|;|');
						}
						else
						{
							suggest_arr = '';
						}
						doSuggest(suggest_arr, useTypeAhead);
			        }
		   		};
		   		request.send(null);
			}
		}
	}

	// function doSuggest
	function doSuggest (suggest_arr, useTypeAhead)
	{
		current = -1;

	    if (suggest_arr.length > 0 && suggest_arr[0] != userText)
	    {
	    	if (useTypeAhead)
	    	{
				typeAhead(suggest_arr[0]);
			}
			showSuggestions(suggest_arr);
	    }
	    else
	    {
	        hideSuggestions();
	    }
	}

	// function typeAhead
	function typeAhead (string)
	{
	    if (textbox.createTextRange || textbox.setSelectionRange){
	        var length = textbox.value.length;
	        textbox.value = string;
	        selectRange(length, string.length);
	    }
	}

 	// function selectRange
	function selectRange (start, end)
	{
	    // use text ranges for Internet Explorer
	    if (textbox.createTextRange) {
	        var range = textbox.createTextRange();
	        range.moveStart("character", start);
	        range.moveEnd("character", end - textbox.value.length);
	        range.select();

	    // use setSelectionRange() for Mozilla
	    } else if (textbox.setSelectionRange) {
	        textbox.setSelectionRange(start, end);
	    }

	    // set focus back to the textbox
	    textbox.focus();
	}

	// function showSuggestions
	function showSuggestions (suggest_arr)
	{
	    var div = null;
	    var data = null;
	    suggestbox.innerHTML = "";

	    for (var i=0; i < suggest_arr.length; i++)
	    {
	    	data = suggest_arr[i].split('|:|');

	        div = document.createElement("div");
	        div.appendChild(document.createTextNode(data[0]));
	        suggestbox.appendChild(div);
	    }

	    suggestbox.style.left = getLeft() + "px";
		suggestbox.style.top = (getTop()+textbox.offsetHeight) + "px";
	    suggestbox.style.visibility = "visible";
	}

	// function showSuggestions
	function hideSuggestions ()
	{
		suggestbox.style.visibility = "hidden";
	}

	// function createDropDown
	function createDropDown ()
	{
	    suggestbox = document.createElement("div");
	    suggestbox.className = "suggestions";
	    suggestbox.style.visibility = "hidden";
	    suggestbox.style.width = textbox.offsetWidth;
	    document.body.appendChild(suggestbox);

	    suggestbox.onmousedown =
	    suggestbox.onmouseup =
	    suggestbox.onmouseover = function (event) {
	        event = event || window.event;
	        target = event.target || event.srcElement;

	        if (event.type == "mousedown") {
	            textbox.value = target.firstChild.nodeValue;
	            hideSuggestions();
	        } else if (event.type == "mouseover") {
	            highlightSuggestion(target);
	        } else {
	            textbox.focus();
	        }
	    };
	}

	// function handleKeyDown
	function handleKeyDown (event)
	{
	    switch(event.keyCode) {
	        case 38: // up arrow
	            goToSuggestion(-1);
	            break;
	        case 40: // down arrow
	            goToSuggestion(1);
	            break;
	        case 27: // esc
	            textbox.value = userText;
	        case 13: // enter
	            hideSuggestions();
	            event.returnValue = false;
	            if (event.preventDefault)
	            {
	                event.preventDefault();
	            }

	            break;
	    }
	}

	// function handleKeyUp
	function handleKeyUp (event)
	{
	    var keyCode = event.keyCode;

		if (keyCode != 38 && keyCode != 40)
		{
	    	userText = textbox.value;
	    }

	    clearTimeout(timeoutId);

	    // for backspace (8) and delete (46), shows suggestions without typeahead
	    if (keyCode == 8 || keyCode == 46)
	    {
	        timeoutId = setTimeout( function ()
	        {
	            requestSuggestions(false);
	        }, 250);

	    // make sure not to interfere with non-character keys
	    }
	    else if (keyCode < 32 || (keyCode >= 33 && keyCode < 46) || (keyCode >= 112 && keyCode <= 123))
	    {
	        // ignore
	    }
	    else
	    {
	        // request suggestions from the suggestion provider with typeahead
	        this.timeoutId = setTimeout( function ()
	        {
	            requestSuggestions(withTypeAhead);
	        }, 250);
	    }
	}

	// function goToSuggestion
	function goToSuggestion (diff)
	{
	    var suggestionNodes = suggestbox.childNodes;

	    if (suggestionNodes.length > 0 && suggestbox.style.visibility == "visible")
	    {
	        var node = null;

	        if (diff > 0)
	        {
	            if (current < suggestionNodes.length-1)
	            {
	                node = suggestionNodes[++current];
	            }
	        }
	        else
	        {
	            if (current > 0)
	            {
	                node = suggestionNodes[--current];
	            }
	        }

	        if (node)
	        {
	            highlightSuggestion(node);
	            textbox.value = node.firstChild.nodeValue;
	        }
	    }
	}

	// function highlightSuggestion
	function highlightSuggestion (suggestionNode)
	{
	    for (var i=0; i < suggestbox.childNodes.length; i++)
	    {
	        var node = suggestbox.childNodes[i];
	        if (node == suggestionNode)
	        {
	            node.className = "current"
	        }
	        else if (node.className == "current")
	        {
	            node.className = "";
	        }
	    }
	}

	// function getLeft
	function getLeft ()
	{
	    var node = textbox;
	    var left = 0;

	    while(node.tagName != "BODY")
	    {
	        left += node.offsetLeft;
	        node = node.offsetParent;
	    }

	    return left;
	}

	// function getTop
	function getTop ()
	{
	    var node = textbox;
	    var top = 1;

	    while(node.tagName != "BODY")
	    {
	        top += node.offsetTop;
	        node = node.offsetParent;
	    }

	    return top;
	}
}
