function AutoSuggestControl(textbox, suggestionsURL)
{
	AutoSuggestControl(textbox, suggestionsURL, null);
}

function AutoSuggestControl(textbox, suggestionsURL, linkedTextbox)
{
	this.cur = -1;
	this.layer = null;
	this.selectableItems = [];
	this.textbox = textbox;
	this.initialTextboxValue = '';
	this.suggestionsURL = suggestionsURL;
	this.linkedTextbox = linkedTextbox;
	this.init();
}

AutoSuggestControl.prototype.init = function ()
{
	var autoSuggestControl = this;

	//assign the ondblclick event handler
	this.textbox.ondblclick = function (event)
	{
		//check for the proper location of the event object
		if (!event)
		{
			event = window.event;
		}

		autoSuggestControl.showDropDown();
		autoSuggestControl.autosuggest("");
	};
	
	//assign the onkeyup event handler
	this.textbox.onkeyup = function (event)
	{
		//check for the proper location of the event object
		if (!event)
		{
			event = window.event;
		}

		autoSuggestControl.handleKeyUp(event);
	};
		
	//assign onkeydown event handler
	this.textbox.onkeydown = function (event)
	{
		//check for the proper location of the event object
		if (!event)
		{
			event = window.event;
		}

		return autoSuggestControl.handleKeyDown(event);
	};
		
	//assign onblur event handler (hides suggestions)
	this.textbox.onblur = function (event)
	{
		event = event || window.event;
		target = event.target || event.srcElement;
		autoSuggestControl.hideSuggestions();
	};
		
	//create the suggestions dropdown
	this.createDropDown();
};

AutoSuggestControl.prototype.createDropDown = function ()
{
	var autoSuggestControl = this;

	this.layer = document.createElement("div");
	this.layer.className = "suggestions";
	this.layer.style.left = this.getLeft() + "px";
	this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + "px";
	this.layer.style.visibility = "hidden";
	this.layer.style.width = this.textbox.offsetWidth + 16 + "px";

	this.layer.onmousedown =
	this.layer.onmouseup =
	this.layer.onmouseover = function (event)
	{
		event = event || window.event;
		target = event.target || event.srcElement;
		
		if (event.type == "mousedown")
		{
			if (autoSuggestControl.updateValues(target))
				autoSuggestControl.hideSuggestions();
		}
		else if (event.type == "mouseover")
		{
			autoSuggestControl.highlightSuggestion(target);
		}
		else
		{
			autoSuggestControl.textbox.focus();
		}
	};


	this.textbox.parentNode.appendChild(this.layer);
};

AutoSuggestControl.prototype.getLeft = function ()
{
	var node = this.textbox;
	var left = 0;

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

	return left - 9;
};

AutoSuggestControl.prototype.getTop = function ()
{
	var node = this.textbox;
	var top = 0;

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

	return top;
};

AutoSuggestControl.prototype.showDropDown = function ()
{
	this.cur = -1;
	var dropdownContent = null;
	this.layer.id = "auto_suggest_dropdown";
	this.layer.innerHTML = ""; //clear contents of the layer
	dropdownContent = document.createElement("div");
	dropdownContent.appendChild(document.createTextNode("searching for suggestions..."));
	this.layer.appendChild(dropdownContent);
	this.selectableItems = [];
	this.layer.style.visibility = "visible";
}

AutoSuggestControl.prototype.autosuggest = function (initialTextboxValue)
{
	if (initialTextboxValue == this.textbox.value)
	{
		var textboxValue = this.textbox.value;

		if (textboxValue.length < 1)
		{
			textboxValue = "";
		}
		sendAjaxRequest(this.suggestionsURL + textboxValue, this.layer.id, 225);
	}
};

AutoSuggestControl.prototype.handleKeyDown = function (event)
{
	switch(event.keyCode)
	{
		case 38: //up arrow
			this.previousSuggestion();
			break;
		case 40: //down arrow
			this.nextSuggestion();
			break;
		case 13: //enter
			this.hideSuggestions();
			return false;
			break;
	}
};

AutoSuggestControl.prototype.handleKeyUp = function (oEvent)
{
	var iKeyCode = oEvent.keyCode;

	//make sure not to interfere with non-character keys
	if (iKeyCode < 8 || (iKeyCode >= 9 && iKeyCode < 32) || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123))
	{
		//ignore
	}
	else
	{
		this.showDropDown();
		var initialTextboxValue = this.textbox.value;
		var autoSuggestControl = this;
		window.setTimeout(function(){autoSuggestControl.autosuggest(initialTextboxValue);}, 300);
	}
};

AutoSuggestControl.prototype.hideSuggestions = function ()
{
	this.layer.id = "";
	this.layer.style.visibility = "hidden";
};

AutoSuggestControl.prototype.highlightSuggestion = function (suggestionNode)
{
	this.loadSelectableItems();
	for (var i=0; i < this.selectableItems.length; i++)
	{
		var node = this.selectableItems[i];
		if (node == suggestionNode || node == suggestionNode.parentNode)
		{
			node.className = "current"
		}
		else if (node.className == "current")
		{
			node.className = "selectable";
		}
	}
};

AutoSuggestControl.prototype.updateValues = function(suggestionNode)
{
	if (suggestionNode.className == "suggestions")
		return false;

	var node = suggestionNode;
	if (node.parentNode.className == "selectable" || node.parentNode.className == "current")
		node = node.parentNode;

	if (this.linkedTextbox == null)
	{
		this.textbox.value = node.childNodes[0].firstChild.nodeValue;
	}
	else
	{
		this.textbox.value = node.childNodes[1].firstChild.nodeValue;
		this.linkedTextbox.value = node.childNodes[0].firstChild.firstChild.nodeValue;
		this.linkedTextbox.onchange();
	}
	
	return true;
}

AutoSuggestControl.prototype.nextSuggestion = function ()
{
	this.loadSelectableItems();
	if (this.selectableItems.length > 0 && this.cur < this.selectableItems.length-1)
	{
		var node = this.selectableItems[++this.cur];
		this.highlightSuggestion(node);
		this.updateValues(node);
	}
};

AutoSuggestControl.prototype.previousSuggestion = function ()
{
	this.loadSelectableItems();
	if (this.selectableItems.length > 0 && this.cur > 0)
	{
		var node = this.selectableItems[--this.cur];
		this.highlightSuggestion(node);
		this.updateValues(node);
	}
};

AutoSuggestControl.prototype.loadSelectableItems = function ()
{
	if (this.selectableItems.length < 1)
	{
		var nodes = this.layer.childNodes;

		for (var i=0; i < nodes.length; i++)
		{
			if (nodes[i].className == "selectable")
			{
				this.selectableItems.push(nodes[i]);
			}
		}
	}
};

AutoSuggestControl.prototype.selectRange = function (start, length)
{
	//use text ranges for Internet Explorer
	if (this.textbox.createTextRange)
	{
		var oRange = this.textbox.createTextRange();
		oRange.moveStart("character", start);
		oRange.moveEnd("character", length - this.textbox.value.length);
		oRange.select();
	}
	//use setSelectionRange() for Mozilla
	else if (this.textbox.setSelectionRange)
	{
		this.textbox.setSelectionRange(start, length);
	}

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


