function AutoSuggestControl(oTextbox, oProvider, doAddNewTextbox){
	this.provider = oProvider;
	this.textbox = oTextbox;
	this.layer = null;
	this.cur = -1;
	this.doAddNewTextbox = Boolean(doAddNewTextbox);
	this.init();
	//alert('Loaded');
	
	this.bTypeAhead = false;
	//this.childASControls = [];
	this.addedNewTextbox = false;
	//this.cancelMouseDown = false;
	
	this.defaultLimit = 15;
	this.currentLimit = this.defaultLimit;
	this.increaseLimit = false;
}

AutoSuggestControl.prototype.selectRange = function(iStart, iLength){
	if(this.textbox.createTextRange){
		//Internet Explorer
		var oRange = this.textbox.createTextRange();
		oRange.moveStart('character', iStart);
		oRange.moveEnd('character', iLength - this.textbox.value.length);
		oRange.select();
	}else if(this.textbox.setSelectionRange){
		//Mozilla
		this.textbox.setSelectionRange(iStart, iLength);
	}
	this.textbox.focus();
};	

AutoSuggestControl.prototype.typeAhead = function(sSuggestion){
	if(this.textbox.createTextRange || this.textbox.setSelectionRange){
		var iLen = this.textbox.value.length;
		this.textbox.value = sSuggestion;
		this.selectRange(iLen, sSuggestion.length);
	}
};

AutoSuggestControl.prototype.autosuggest = function(aSuggestions, bTypeAhead){
	if(aSuggestions.length > 0){
		if(bTypeAhead){
			this.typeAhead(aSuggestions[0]);
		}
		this.showSuggestions(aSuggestions);
	}else{
		this.hideSuggestions();
	}
};

AutoSuggestControl.prototype.handleKeyUp = function(oEvent){
	var iKeyCode = oEvent.keyCode;
	if(iKeyCode == 8 || iKeyCode == 46){
		this.provider.requestSuggestions(this, false);
	}else if(iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode <= 46) || (iKeyCode >= 112 && iKeyCode <= 123)){
		//ignore
	}else{
		//autosuggest
		this.provider.requestSuggestions(this, this.bTypeAhead);
	}
};

AutoSuggestControl.prototype.init = function(){
	var oThis = this;
	this.textbox.onkeyup = function(oEvent){
		if(!oEvent){
			oEvent = window.event;
		}
		oThis.handleKeyUp(oEvent);
	};
	this.textbox.onkeydown = function(oEvent){
		if(!oEvent){
			oEvent = window.event;
		}
		oThis.handleKeyDown(oEvent);
	};
	this.textbox.onblur = function(oEvent){
		oThis.hideSuggestions();
	}
	//custom 
	//alert(this.doAddNewTextbox);
	if (this.doAddNewTextbox) {
		this.textbox.onchange = function(oEvent){
			//this.cancelMouseDown = true;
			if(oThis.textbox.value){
				if(!oEvent){
					oEvent = window.event;
				}
				var new_textbox = oThis.textbox.cloneNode(false);
				//new_textbox.setAttribute('name', 'school_name[]');
				new_textbox.value = '';
				var asControlChild = new AutoSuggestControl(new_textbox, new SuggestionProvider(), true);
				oThis.textbox.parentNode.appendChild(new_textbox);
				
				oThis.addedNewTextbox = true;
			}
		}
	}
	
	this.createDropDown();
};

function SuggestionProvider(){
	//
	if (typeof XMLHttpRequest != "undefined") {
        this.http = new XMLHttpRequest();
    } else if (typeof ActiveXObject != "undefined") {
        this.http = new ActiveXObject("MSXML2.XmlHttp");
    } else {
        alert("No XMLHttpRequest object available. This functionality will not work.");
    }
}

SuggestionProvider.prototype.requestSuggestions = function(oAutoSuggestControl, bTypeAhead){
	var oHttp = this.http;
	
	if (oHttp.readyState != 0) {
        oHttp.abort();
    }
    var sURL = "auto_suggest.php?type=school_name&userInput=" + encodeURIComponent(oAutoSuggestControl.textbox.value);
	////
	if(oAutoSuggestControl.increaseLimit){
		sURL += '&limit=' + oAutoSuggestControl.currentLimit;
	}
	////
	//alert(sURL);
    oHttp.open("get", sURL , true);
    oHttp.onreadystatechange = function () {
        if (oHttp.readyState == 4) {
			//alert(oHttp.responseText);
            var aSuggestions = eval(oHttp.responseText);
			if(typeof(aSuggestions) == 'undefined'){
				aSuggestions = new Array();
			}
            oAutoSuggestControl.autosuggest(aSuggestions, bTypeAhead);
        }
    };
    oHttp.send(null);
};

function SuggestionProviderSports(){
	//
	if (typeof XMLHttpRequest != "undefined") {
        this.http = new XMLHttpRequest();
    } else if (typeof ActiveXObject != "undefined") {
        this.http = new ActiveXObject("MSXML2.XmlHttp");
    } else {
        alert("No XMLHttpRequest object available. This functionality will not work.");
    }
}

SuggestionProviderSports.prototype.requestSuggestions = function(oAutoSuggestControl, bTypeAhead){
	var oHttp = this.http;
	
	if (oHttp.readyState != 0) {
        oHttp.abort();
    }
	
	var gender = 'men';
	var genderMenRadio = document.getElementById('radio_sports_men');
	var genderWomenRadio = document.getElementById('radio_sports_women');
	if (genderMenRadio && genderMenRadio.checked) {
		gender = genderMenRadio.value;
	} else if (genderWomenRadio && genderWomenRadio.checked) {
		gender = genderWomenRadio.value;
	}
	
    var sURL = "auto_suggest.php?type=sport&gender=" + gender + "&userInput=" + encodeURIComponent(oAutoSuggestControl.textbox.value);
	//alert(sURL);
    oHttp.open("get", sURL , true);
    oHttp.onreadystatechange = function () {
        if (oHttp.readyState == 4) {
			//alert(oHttp.responseText);
            var aSuggestions = eval(oHttp.responseText);
			if(typeof(aSuggestions) == 'undefined'){
				aSuggestions = new Array();
			}
            oAutoSuggestControl.autosuggest(aSuggestions, bTypeAhead);
        }
    };
    oHttp.send(null);
};

////////////////////// test.html

function StateSuggestions(){
	this.states = ["Alabama", "Illinois", "Nebraska", "Niger"];
}

StateSuggestions.prototype.requestSuggestions = function(oAutoSuggestControl, bTypeAhead){
	var aSuggestions = [];
	var sTextboxValue = oAutoSuggestControl.textbox.value;
	
	if(sTextboxValue.length > 0){
		var sTextboxValueLC = sTextboxValue.toLowerCase();
		for(var i = 0; i < this.states.length; i++){
			var sStateLC = this.states[i].toLowerCase();
			if(sStateLC.indexOf(sTextboxValueLC) == 0){
				//aSuggestions.push(this.states[i]);
				aSuggestions.push(sTextboxValue + this.states[i].substring(sTextboxValue.length));
			}
		}
		oAutoSuggestControl.autosuggest(aSuggestions, bTypeAhead);
	}
};

//////////////////////////////////////

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

AutoSuggestControl.prototype.highlightSuggestion = function(oSuggestionNode){
	for(var i = 0; i < this.layer.childNodes.length; i++){
		var oNode = this.layer.childNodes[i];
		if(oNode == oSuggestionNode){
			oNode.className = 'current';
		////
		}else if(oNode.className != 'more_link'){
		////
			oNode.className = '';
		}
	}
};

AutoSuggestControl.prototype.createDropDown = function(){
	this.layer = document.createElement('div');
	this.layer.className = 'suggestions';
	this.layer.style.visibility = 'hidden';
	//this.layer.style.width = this.textbox.offsetWidth + 'px';
	//alert(this.layer.style.width);
	document.body.appendChild(this.layer);
	
	var oThis = this;
	this.layer.onmousedown = this.layer.onmouseup = this.layer.onmouseover = function(oEvent){
		oEvent = oEvent || window.event;
		oTarget = oEvent.target || oEvent.srcElement;
		
		if(oEvent.type == 'mousedown'){
			/////
			//alert(oThis.increaseLimit);
			if(!oThis.increaseLimit){
				oThis.textbox.value = oTarget.firstChild.nodeValue;
			}else{
				oThis.increaseLimit = false;
			}
			/////
			oThis.hideSuggestions();
			
			//add new textbox (custom)
			if(!this.addedNewTextbox && document.all){
				//var new_textbox = document.createElement('INPUT');
				var new_textbox = oThis.textbox.cloneNode(false);
				//new_textbox.setAttribute('name', 'school_name[]');
				new_textbox.value = '';
				var asControlChild = new AutoSuggestControl(new_textbox, new SuggestionProvider());
				oThis.textbox.parentNode.appendChild(new_textbox);
				
				this.addedNewTextbox = true;
			}		
		}else if(oEvent.type == 'mouseover'){
			oThis.highlightSuggestion(oTarget);
		}else{
			oThis.textbox.focus();
		}
	};
};

AutoSuggestControl.prototype.getLeft = function(){
	var oNode = this.textbox;
	var iLeft = 0;
	while(oNode.tagName != 'BODY'){
		iLeft += oNode.offsetLeft;
		oNode = oNode.offsetParent;
	}
	return iLeft;
};

AutoSuggestControl.prototype.getTop = function(){
	var oNode = this.textbox;
	var iTop = 0;
	while(oNode.tagName != 'BODY'){
		iTop += oNode.offsetTop;
		oNode = oNode.offsetParent;
	}
	return iTop;
};

AutoSuggestControl.prototype.showSuggestions = function(aSuggestions){
	var oThis = this;
	var oDiv = null;
	this.layer.innerHTML = '';
	for(var i = 0; i < aSuggestions.length; i++){
		//if(aSuggestions[i] != 'undefined'){
			oDiv = document.createElement('div');
			oDiv.appendChild(document.createTextNode(aSuggestions[i]));
			this.layer.appendChild(oDiv);
		//}
	}
	////john 26.05.2009, add 'more' link
	//alert(aSuggestions.length + ' ' + oThis.currentLimit);
	if(aSuggestions.length >= oThis.currentLimit){
		oDiv = document.createElement('div');
		oDiv.appendChild(document.createTextNode('(+) more...'));
		oDiv.onmousedown = function(){ 
			//alert('request more');
			oThis.increaseLimit = true;
			oThis.currentLimit += oThis.defaultLimit;
			oThis.provider.requestSuggestions(oThis, oThis.bTypeAhead);
		};
		oDiv.className = 'more_link';
		//oDiv.style.backgroundColor = '#DD1122';
		this.layer.appendChild(oDiv);
	}else{
		oThis.currentLimit = aSuggestions.length;
	}
	
	////
	
	this.layer.style.left = this.getLeft() + 'px';
	this.layer.style.top = (this.getTop() + this.textbox.offsetHeight) + 'px';
	this.layer.style.visibility = 'visible';
	
};


AutoSuggestControl.prototype.nextSuggestion = function(){
	var cSuggestionNodes = this.layer.childNodes;
	if(cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length - 1){
		var oNode = cSuggestionNodes[++this.cur];
		this.highlightSuggestion(oNode);
		this.textbox.value = oNode.firstChild.nodeValue;
	}
};

AutoSuggestControl.prototype.previousSuggestion = function(){
	var cSuggestionNodes = this.layer.childNodes;
	if(cSuggestionNodes.length > 0 && this.cur > 0){
		var oNode = cSuggestionNodes[--this.cur];
		this.highlightSuggestion(oNode);
		this.textbox.value = oNode.firstChild.nodeValue;
	}
};

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