var useNs;

if (useNs)	{
	if (typeof($) == "undefined")
		$ = {}
	_ = $;
	} else {
		_ = this;
		}

if (typeof(_.DOM) == "undefined")
	_.DOM = {}

_.AutoSuggest = function (fldID, param) {
	if (!document.getElementById)
		return false;
	
	this.fld = _.DOM.getElement(fldID);

	if (!this.fld)
		return false;		
		
	this.nInputChars = 0;
	this.aSuggestions = [];
	this.aSuggestionsId = [];
	this.iHighlighted = 0;	
	
	// parameters object
	this.oP = (param) ? param : {};
	// defaults	
	if (!this.oP.linkPage) this.oP.linkPage = "";
	if (!this.oP.minchars) this.oP.minchars = 1;
	if (!this.oP.method)	 this.oP.meth = "get";
	if (!this.oP.varname)	 this.oP.varname = "input";
	if (!this.oP.className)this.oP.className = "autosuggest";
	if (!this.oP.timeout)	 this.oP.timeout = 1250;
	if (!this.oP.delay)		 this.oP.delay = 500;
	if (!this.oP.maxheight && this.oP.maxheight !== 0) this.oP.maxheight = 120;
	if (!this.oP.cache)		 this.oP.cache = true;
	
	var pointer = this;
	
	this.fld.onkeyup = function () { pointer.getSuggestions( this.value ) };
	this.fld.setAttribute("autocomplete","off");
	}

_.AutoSuggest.prototype.getSuggestions = function (val) {

	if (val.length == this.nInputChars)
		return false;
	
	if (val.length < this.oP.minchars) {
		this.nInputChars = val.length;
		this.aSuggestions = [];
		this.aSuggestionsId = [];
		this.clearSuggestions();
		return false;
		}

	if (val.length>this.nInputChars && this.aSuggestions.length && this.aSuggestionsId && this.oP.cache) {
		// get from cache
		var arr = [];
		var arrId = [];
		for (var i=0;i<this.aSuggestions.length;i++) {
			if (this.aSuggestions[i].substr(0,val.length).toLowerCase() == val.toLowerCase())
				arr.push( this.aSuggestions[i] );
				arrId.push( this.aSuggestionsId[i] );
			}
		
		this.nInputChars = val.length;
		this.aSuggestions = arr;
		this.aSuggestionsId = arrId;
		this.createList( this.aSuggestions, this.aSuggestionsId );
		
		return false;
		}	
	
	this.nInputChars = val.length;
	
	var pointer = this;
	clearTimeout(this.ajID);
	this.ajID = setTimeout( function() { pointer.doAjaxRequest() }, this.oP.delay );

	return false;
	}

_.AutoSuggest.prototype.doAjaxRequest = function () {
	var pointer = this;
	
	var region = "";
	// create ajax request
	var url = this.oP.script+this.oP.varname+"="+escape(this.fld.value)+"&location_id="+region;
	var meth = this.oP.meth;
	
	var onSuccessFunc = function (req) { pointer.setSuggestions(req) };
	var onErrorFunc = function (status) { alert("AJAX error: "+status); };

	var myAjax = new _.AjaxSuggest;
	myAjax.makeRequest( url, meth, onSuccessFunc, onErrorFunc );
	}

_.AutoSuggest.prototype.setSuggestions = function (req) {
	
	var xml = req.responseXML;
	
	// traverse xml
	this.aSuggestions = [];
	this.aSuggestionsId = [];
	var results = xml.getElementsByTagName('results')[0].childNodes;

	for (var i=0;i<results.length;i++) {
		if (results[i].hasChildNodes()) {
			this.aSuggestions.push( results[i].childNodes[0].nodeValue );
			if(results[i].childNodes[0].nodeValue != "No results match your search criteria") {
				this.aSuggestionsId.push(results[i].attributes.getNamedItem("id").value);			
				}
			}
		}
		
	this.idAs = "as_"+this.fld.id;			
	this.createList(this.aSuggestions, this.aSuggestionsId );
	}

_.AutoSuggest.prototype.createList = function(arr, arrId) {
	this.clearSuggestions();

	// create and populate ul
	var ul = _.DOM.createElement("ul", {id:this.idAs, className:this.oP.className});
		
	var pointer = this;
	for (var i = 0; i < arr.length; i++) {
		
		var myHref = (this.oP.linkPage) ? this.oP.linkPage + arrId[i] : "#";
		var a = _.DOM.createElement("a", { href: myHref }, arr[i]);
		
		if(!this.oP.linkPage) {
			a.onclick = function () { pointer.setValue( this.childNodes[0].nodeValue ); return false; }			
			}
		
		var li = _.DOM.createElement(  "li", {}, a  );
		ul.appendChild(  li  );
		}
			
	var pos = _.DOM.getPos(this.fld);
	
	ul.style.left = parseInt(pos.x + 2) + "px";
	ul.style.top = ( pos.y + this.fld.offsetHeight ) + "px";
	ul.style.width = this.fld.offsetWidth + "px";
	ul.onmouseover = function(){ pointer.killTimeout() }
	ul.onmouseout = function(){ pointer.resetTimeout() }
	
	document.getElementsByTagName("body")[0].appendChild(ul);
	
	if (ul.offsetHeight > this.oP.maxheight && this.oP.maxheight != 0) {
		ul.style['height'] = this.oP.maxheight + "px";
		}
	
	var TAB = 9;
	var ESC = 27;
	var KEYUP = 38;
	var KEYDN = 40;
	var RETURN = 13;
	
	this.fld.onkeydown = function(ev) {
		var key = (window.event) ? window.event.keyCode : ev.keyCode;

		switch(key) {
			case TAB:
			pointer.setHighlightedValue();
			break;

			case ESC:
			pointer.clearSuggestions();
			break;

			case KEYUP:
			pointer.changeHighlight(key);
			return false;
			break;

			case KEYDN:
			pointer.changeHighlight(key);
			return false;
			break;
			}

	};

	this.iHighlighted = 0;
			
	// remove autosuggest after an interval
	clearTimeout(this.toID);
	var pointer = this;
	this.toID = setTimeout(function () { pointer.clearSuggestions() }, this.oP.timeout);
	}

_.AutoSuggest.prototype.changeHighlight = function(key) {
	var list = _.DOM.getElement(this.idAs);
	if (!list)
		return false;
		
	if (this.iHighlighted > 0)
		list.childNodes[this.iHighlighted-1].className = "";
	
	if (key == 40)
		this.iHighlighted ++;
	else if (key = 38)
		this.iHighlighted --;
		
	if (this.iHighlighted > list.childNodes.length)
		this.iHighlighted = list.childNodes.length;
	if (this.iHighlighted < 1)
		this.iHighlighted = 1;
	
	list.childNodes[this.iHighlighted-1].className = "highlight";		
	
	this.killTimeout();
	}

_.AutoSuggest.prototype.killTimeout = function() {
	clearTimeout(this.toID);
	}

_.AutoSuggest.prototype.resetTimeout = function() {
	clearTimeout(this.toID);
	var pointer = this;
	this.toID = setTimeout(function () { pointer.clearSuggestions() }, 1000);
	}

_.AutoSuggest.prototype.clearSuggestions = function () {
	if (document.getElementById(this.idAs))
		_.DOM.removeElement(this.idAs);
	this.fld.onkeydown = null;
	}

_.AutoSuggest.prototype.setHighlightedValue = function () {
	if (this.iHighlighted) {
		this.fld.value = document.getElementById(this.idAs).childNodes[this.iHighlighted-1].firstChild.firstChild.nodeValue;
		this.killTimeout();
		this.clearSuggestions();
		}
	}

_.AutoSuggest.prototype.setValue = function (val) {
	this.fld.value = val;
	this.clearSuggestions();
	this.resetTimeout();
}