function suggest(obj_target, result_id, ajax_obj){

	var self = this;

	this.target = null; //input box
	this.disableKeyPressEvents = true; // set to true to shut off the suggest pulldown lists
	this.service = false;
	this.goldenWareUrl = "";
	this.ajax   = ajax_obj;
	this.unselectedClass = 'sr';
	this.selectedClass = 'srs';
	this.noCitiesMsg = "No Airports - Please backspace";
	this.holdUnselectedClas = false;
	this.ALTunselectedClass = ''; //color of partner flight on the pulldown
	this.parentObj = false;
	this.childObj = false;
	this.threshold = false;
	this.overLapObj = false;
	this.showOverLapObj = false;
	this.overLapObjType = "block";
	this.waiteTime = 230; //milliseconds
	this.tp = 0;
	this.maxResultCount = 15;
	this.format = 'text';
	this.lastReq = '';
	this.show = false;
	this.relation = false;
	this.selectedNode = false;
	this.selectedEle = false;
	this.resultDiv = document.getElementById(result_id); //div results are displayed in
	if(!this.resultDiv)alert("Invalid Element id");
	

	// validate input parameters
	if (!obj_target)
		return false;
	if (obj_target.value == null)
		return false;

	this.target = obj_target;
	this.getCodeFromName = function(val){
		reg = /\(([a-z]{3})\)/i;
		arr = reg.exec(val);
		if(!arr)
		{	
			reg = /([\w\s\'\(\)]{3,10})/i;
			arr = reg.exec(val);
		}
		return (arr ? arr[1] : false);
	};
	if(this.target.value != '')
		this.relation = this.getCodeFromName(this.target.value);

	this.target.onkeydown = function (e){
		//alert(key);
		if(self.disableKeyPressEvents == false)
		{
			var key = self.getkeycode(e);
			switch (key) {
				case 9: //tab
					/*return false;*/
					break;
				case 13: //enter
					listEle = self.getFirstChild(self.resultDiv);
					if(listEle)
					{
						self.showHideOverLapObj(false);
						self.selectAndHide(listEle.childNodes[self.selectedNode]);
					}
					return false;
					break;
				case 27: // escape
					listEle = self.getFirstChild(self.resultDiv);			
					if(listEle)
					{
						self.showHideOverLapObj(false);
						self.selectAndHide(listEle.childNodes[self.selectedNode]);
					}
					return false;
					break;
				case 38: // up arrow
					self.selectUp();
					return false;
					break;
				case 40: // down arrow
					self.selectDown();
					return false;
					break;
				default:
					if(key != 9 && key != 16 && key != 18)
					{
						self.startTimer(self.makeReq, self.waiteTime);
						self.relation = false;
					}
			}
		}
		return true;
	};

	this.setInLineLabel = function(label){
		this.inLineLabel = label;
		if(this.target.value == "")
		{
			this.target.value = label;
			this.target.className = "labelClass";
		}

	};

	this.blurEvent = function(e){
		self.showHideOverLapObj(false);
		ele = self.getElementTrigger(e);

			if(self.resultDiv.style.display == 'block')
			{
				listEle = self.getFirstChild(self.resultDiv);
				if(listEle)
				{
					if(listEle.childNodes[self.selectedNode])
					{
						city = self.trim(listEle.childNodes[self.selectedNode].childNodes[0].innerHTML);
						if(city != self.noCitiesMsg) ele.value = city;
					}else if(self.selectedEle) {
						city = self.trim(self.selectedEle.childNodes[0].innerHTML);
						if(city != self.noCitiesMsg) ele.value = city;
					}
				}
			}
		
		self.hideResultDiv();
		if(self.relation == false)
		{
			
			if(ele.value.length > 2)
			{
				self.relation = self.getCodeFromName(ele.value);
			}else self.relation = false;
		}
		if(ele.value == '' && self.inLineLabel)
		{
			ele.value = self.inLineLabel;
			ele.className = "labelClass";
		}
	};
	this.focusEvent = function(e)
	{
		ele = self.getElementTrigger(e);
		if(ele.value == self.inLineLabel)
		{
			ele.value = '';
			ele.className = "null";
		}
	}
	this.target.onblur = this.blurEvent;
	this.target.onfocus = this.focusEvent;
	this.selectDown = function(){
		this.clearSelected();
		this.moveSelection("down");
	}
	this.selectUp = function(){
		this.clearSelected();
		this.moveSelection("up");
	};
	this.moveSelection = function(dir) {
		listEle = this.getFirstChild(this.resultDiv);
		if(dir == "up")m = -1;
		if(dir == "down")m = 1
		if(this.selectedNode + m >= listEle.childNodes.length || this.selectedNode + m < 0) m = 0;
		this.selectedNode = this.selectedNode + m;
		this.holdUnselectedClass = listEle.childNodes[this.selectedNode].className;
		listEle.childNodes[this.selectedNode].className = this.selectedClass;
		city = listEle.childNodes[this.selectedNode].childNodes[0].innerHTML;
		this.target.value = city;
		this.relation = this.getCodeFromName(city);
		
	};
	this.setChildObj = function(child){
		this.childObj = child;
	};
	this.setParentObj = function(parent){
		this.parentObj= parent;
	};
	this.setMaxResultCount = function(count){
		this.maxResultCount = count;
	};
	this.setFormat = function(format){
		this.format = format;
	};
	this.setService = function(service){
		this.service = service;
	};
	this.startTimer = function(cmd, ms) {
		if (this.tp > 0)
			this.resetTimer();
		this.tp = window.setTimeout(cmd, ms);
	};
	this.resetTimer = function(){
		if (this.tp > 0)
			window.clearTimeout(this.tp);
		this.tp = 0;
	};
	this.getkeycode = function(e){
		if (document.layers)
			return e.which;
		else if (document.all)
			return event.keyCode;
		else if (document.getElementById)
			return e.keyCode;
		return 0;
	};
	this.getObjName = function(){
		for(var i in global) 
		{
			if(global[i] == this){
				return global[i];
			}
		}
	};
	//element to be overlapped. threshold = number of results it takes to cover object
	this.setOverLapObjX = function(eleId, threshold, type){
		this.overLapObjType = type;
		ele = document.getElementById(eleId);
		if(ele)
		{
			//alert("setOverLapObj: setting overlap div.");
			this.overLapObj = ele;
			this.threshold = threshold;
		}else return false;//alert("setOverLapObj:" + eleId + " is not a valid element ID.");

	};
	this.setOverLapObj = function(assArray, type){
		this.overLapObjType = type;
		this.overLapObj = assArray;
	};
	this.showHideOverLapObj = function(len)
	{
		if(this.overLapObj)
		{
			for(x in this.overLapObj)
			{
				ele = document.getElementById(x);
				if(len >= this.overLapObj[x])
				{
					ele.style.display = "none";
				}else {
					ele.style.display = this.overLapObjType;
				}
			}
		}
	};
	this.showHideOverLapObjX = function(len)
	{
		if(this.overLapObj && this.threshold)
		{
				if(len >= this.threshold)
				{
					//alert("showHideOverLapObj: hiding.");
					this.overLapObj.style.display = 'none';
					//this.showOverLapObj = true;
				}else {
					this.overLapObj.style.display = this.overLapObjType;
				}
		}
	};
	this.makeReq = function(){
		childField  = false;
		parentField = false;
		if(self.target.value == '')
		{
			self.showHideOverLapObj(false);
			self.hideResultDiv();
			return false;
		}
		//if(self.target.value == self.lastReq) return false;
		if(self.childObj != false)
			if(self.childObj.target.value != '')
				childField = self.childObj.relation;

		if(self.parentObj != false)
			if(self.parentObj.target.value != '')
				parentField = self.parentObj.relation;
				
		self.lastReq = self.target.value;
		url =	self.service + '?mode=query'
				+ "&count=" + self.maxResultCount
				+ "&format=" + self.format 
				+ (parentField ? "&parent=" + encodeURI(parentField) : '')
				+ (childField  ? "&child="  + encodeURI(childField)  : '')
				+ '&q=' + self.target.value;
		//alert(url);
		self.ajax.doGet(url, self.handleReq, self.format);
	};
	this.printResultJsArray = function(resArr) {
		if(resArr.length > 0)
		{
//			alert(resArr);
			this.showHideOverLapObj(resArr.length);
			imgFolder = this.goldenWareUrl + '/img';
			obj = this.getObjName();
			this.holdUnselectedClass = this.unselectedClass;
			list = '<ul class="suggestResults" >';
			for(i in resArr)
			{
//				code = resArr[i];
//				alert(code);
				sr = this.unselectedClass;
				if(resArr[i].match(/\+$/))
				{
					len = resArr[i].length - 1;
					resArr[i] = resArr[i].substr(0, len);
					sr = this.ALTunselectedClass;
					if(i == 0)
					{
						this.holdUnselectedClass = sr;
					}
				}
				list += '<li class="' + (i == 0 ? this.selectedClass : sr ) //srs and sr are references to css classes.
				     +'" onmouseover="obj.mouseOver(event);return true"'
				     //+'onmouseout="obj.mouseOut(event);return true" '
			             +'onmousedown="obj.mouseClick(event);return true"><span>'
				     + resArr[i] + '</span> ' 
// gman made change here... ^^^^ 
//				     + '<img class="carrier" src="' 
//				     + ((i % 2 == 0) ? imgFolder + '/fl.jpg' : imgFolder + '/f9.jpg') + '"' 
//				     + 'alt="carrier">'
			             + '</li>';

			}
			list += "</ul>";
			this.selectedNode = 0;
			this.resultDiv.innerHTML = list;
			this.showResultDiv();
		}else {
			this.showHideOverLapObj(false);
			this.hideResultDiv();
		}
	};
	this.printResultJsArrayDivs = function(resArr){
		if(resArr.lenght > 0)
		{
			out = '';
			obj = this.getObjName();
			for(i in resArr)
			{
				out += '<div class="' + (i==0 ? 'srs' : '') + '" '
				     + 'onmouseover="obj.mouseOver(event); return true" '
				     + 'onmouseout="obj.mouseOut(event);return true" '
                     + 'onmousedown="obj.mouseClick(event);return true">'
				     + '<span class="name">' + resArr[i] + '</span>'
				     + '<span class="code">' + '(XXX)' + '</span>'
				     + '</div>';
			}
			this.resultDiv.innerHTML = out;
			this.showResultDiv();

		}
	};
	this.selectAndHide = function(ele){

			try{
				city = this.trim(this.selectedEle.childNodes[0].innerHTML);
			}catch (e) {
				try{
					city = this.trim(this.getTargetVal(ele));
				}catch(e){
				//
				}
			}
		
			if(city && city != this.noCitiesMsg)
			{
				this.target.value = city;
				this.relation = this.getCodeFromName(city);
			}
			this.hideResultDiv();
	};

	//THIS FUNCTION IS NOT USED ANYMORE
	this.getTargetVal = function(ele){
		var ret
		if(ele)
		{
			if(ele.nodeName != "LI")
			{
				ret = ele.parentNode.childNodes[0].innerHTML;
				//alert(ret);
				return ret;
			}else return ele.childNodes[0].innerHTML;		
		}
	};
	this.mouseClick = function(e){
		ele = this.getElementTrigger(e);
		//alert(ele.nodeName);
		this.showHideOverLapObj(false);
		this.selectAndHide(ele);
	};
	this.mouseOver = function(e){
		this.clearSelected();
		this.highlightNode(this.getElementTrigger(e), true);
	};
	this.mouseOut = function(e){
		this.highlightNode(this.getElementTrigger(e), false);
	};
	this.highlightNode = function(ele, hilight){
		if(ele.nodeName != "LI") ele = ele.parentNode;
		if(this.selectedEle) this.selectedEle['className'] = this.holdUnselectedClass;
		if(hilight)
		{
			if(ele['className'] == this.ALTunselectedClass)
			{
				this.holdUnselectedClass = this.ALTunselectedClass;
			}else this.holdUnselectedClass = this.unselectedClass;
			ele['className'] = this.selectedClass;
			this.selectedNode = false;
			this.selectedEle = ele;
		}
		else ele['className'] = this.holdUnselectedClass;
	};

	this.getFirstChild = function(n){
		var x=n.firstChild;
		if (x != null)
		{
		while (x.nodeType!=1)
		{
			x=x.nextSibling;
		}
		}
		
		//alert(x.nodeName);
		return x;
	};
	this.clearSelected = function() {
		listEle = this.getFirstChild(this.resultDiv);
		if(this.selectedNode == false){
			for (i=0; i<listEle.childNodes.length; i++)
			{
				if (listEle.childNodes[i].nodeName=="LI"){
					//alert("LI " + i);
					if(listEle.childNodes[i].className){
						//alert("has class attr " + i);
					
						if(listEle.childNodes[i].className == this.selectedClass){
							this.selectedNode = i;
							//alert("changing classattr " + i);
							listEle.childNodes[i].className = this.holdUnselectedClass;
						}
					}
				}


			}
		}else {
			listEle.childNodes[this.selectedNode].className = this.holdUnselectedClass;
		}
	};
	this.getElementTrigger = function(ele){
		var targ;
		if (!ele) var ele = window.event;
		if (ele.target) targ = ele.target;
		else if (ele.srcElement) targ = ele.srcElement;
		if (targ.nodeType == 3) // defeat Safari bug
			targ = targ.parentNode;

		return targ;
	};

	this.showResultDiv = function(){
		if(!this.show)
		{
			//alert(this.target.id + " show me");
			this.resultDiv.style.display = 'block';
			this.show = true;
		}

	};
	this.hideResultDiv = function() {
		this.resultDiv.innerHTML = null;
		this.resultDiv.style.display = 'none';
		this.selectedNode = false;
		this.show = false;
	};
	this.trim = function(st){
		return st.replace(/^\s+|\s+$/g,"");
	}
	this.handleReq = function(str){
		if(str != '')
		{
			switch(this.responseFormat)//handleReq runs in the ajax class scope. making the method 
			{
				case 'text':
					//alert(':'+str);
					break;
			        case 'jsarray':
					//alert(str);
					eval('var resp =' + str);
					//alert(str);
					//self a reference to suggest class much be used. 
					//becuase this handler function runs in the ajax class scope
					self.printResultJsArray(resp);
				  break;
				case 'xml':
					break;
				default:

			}
		}

	};
	this.isArray = function (obj) {
		return (obj.constructor.toString().indexOf("Array") == -1) ? false : true;
	};

}