Ajax.implement({
	responseIsSuccess: function(status){
		try {
			if(this.transport.readyState != 4 || this.transport.status == "undefined" || (this.transport.status <= 200 || this.transport.status >= 300)) {
				return true;
			}
		} catch(e) {
			return false;
		}
	},
	responseIsFailure: function(){
		return !this.responseIsSuccess();
	},
	onStateChange: function(){
		if (this.transport.readyState == 4 && this.responseIsSuccess()){
			if (this.options.update) $(this.options.update).setHTML(this.transport.responseText);
			this.options.onComplete.pass([this.transport.responseText, this.transport.responseXML], this).delay(20);
			if (this.options.evalScripts) this.evalScripts.delay(30, this);
			this.transport.onreadystatechange = Class.empty;
			this.callChain();
		} else if(this.transport.readyState == 4 && this.responseIsFailure()) {
			if($type(this.options.onFailure)=='function') this.options.onFailure.pass(this.transport, this).delay(20); 
		}
	}
});

Element.extend({
	hide: function() {
		this.style.display = 'none';
		return this;
	},
	show: function() {
		this.style.display = '';
		return this;
	}
});

var AjaxAutoCompleter = new Class({ 
	initialize: function(element, choices, url, options) { 
		this.options = Object.extend({ 
			minChars: 2, 
			delay: 400, 
			indicator: null 
		}, options || {}); 
		if (this.options.indicator != null) { 
			this.indicator = $(this.options.indicator); 
		} 
		this.element = $(element); 
		this.choices = $(choices); 
		this.url = url; 
		this.choices.hide();
		this.currentValue = ''; 
		this.element.setAttribute("autocomplete", "off"); 
		this.element.addEvent('keyup', this.onTextChange.bindAsEventListener(this)); 
	}, 
	onTextChange: function() { 
		if (this.fetchDelay) { 
			this.fetchDelay = $clear(this.fetchDelay); 
		} 
		this.fetchDelay = this.fetch.delay(this.options.delay, this); 
	}, 
	
	fetch: function() { 
		if (this.element.value.length <= this.options.minChars) { 
			this.choices.hide(); 
		} else { 
			if (this.element.value != this.currentValue) { 
				this.currentValue = this.element.value; 
				this.clearSelected(); 
				this.choices.show(); 
				if (this.indicator) { 
					this.indicator.show(); 
				} 
				var myAjax = new Ajax(this.url + this.element.value, { method: 'get', onFailure:this.onFailure, onComplete:this.onSuccess.bindAsEventListener(this)}).request(); 
			} 
		} 
	}, 
		
	onFailure: function(response) { 
		if (this.indicator) { 
			this.indicator.hide(); 
		} 
		alert('There was a problem! \n' + response.status + ' -- ' + response.statusText);
	}, 
	
	onSuccess: function(response) { 
		if (this.indicator) { 
			this.indicator.hide(); 
		} 
		if (response.trim() == '') { 
			this.choices.hide(); 
		} else { 
			this.choices.setHTML(response); 
		} 
	}, 

	clearSelected: function() { 
		$ES('div.selected', this.choices).each(function (el) { 
			el.removeClass('selected'); 
		}); 
	}
}); 
