(function($) { 
	$.fn.extend({
		autosuggest: function(options) {  
			var defaults = {
				field_id	: '',
				results_id	: 'results',  
				url			: 'search.php',
				resultDiv	: null
			}  
			
			var options = $.extend({}, defaults, options);
			
			return this.each(function() {
				var o = options;
				var obj = $(this);
				$(obj).attr('autocomplete', 'off');
				$.autosuggest(obj, o.field_id, o.results_id, o.url);
			});  
		},
	});
	
	var delay		= 500;
	var listTotal	=  0;
	var listCurrent	= -1;
	
	$.autosuggest = function(obj, field_id, results_id, url)
	{
		var resultsId	= results_id + '-' + field_id;
		
		$("body").append('<div id="' + resultsId + '" class="results"></div>');
		
		var field		= $('#'+field_id);
		var results		= $('#'+resultsId);
		
		$.repositionResultsDiv(field, results);
		
		field.blur(function(){ setTimeout("$.clearAutoComplete('"+resultsId+"')", 200); });
		
		field.keyup(function(e) {
			
			// get keyCode (window.event is for IE)
			var keyCode = e.keyCode || window.event.keyCode;
			var lastVal = field.val();
	
			// check an treat up and down arrows
			if($.updownArrow(keyCode, results, field)){
				return;
			}
	
			// check for an ENTER or ESC
			if(keyCode == 13 || keyCode == 27){
				$.clearAutoComplete(resultsId);
				return false;
			}
	
			// if is text, call with delay
			$.autoComplete(field, results, resultsId, url, lastVal);
		});
		
	}
	
	$.repositionResultsDiv = function(field, results)
	{
		// get the field position
		var sf_pos    = field.offset();
		var sf_top    = sf_pos.top;
		var sf_left   = sf_pos.left;
	
		// get the field size
		var sf_height = field.height();
		var sf_width  = field.width();
	
		// apply the css styles - optimized for Firefox
		results.css("position","absolute");
		results.css("left", sf_left - 2);
		results.css("top", sf_top + sf_height + 5);
		results.css("width", sf_width - 2);
		results.css("z-index", 9999);
	}
	
	$.autoComplete = function(field, results, results_id, url, lastValue)
	{
		// get the field value
		var part = field.val();
	
		// if it's empty clear the resuts box and return
		if(part == ''){
			$.clearAutoComplete(results_id);
			return;
		}
	
		// if it's equal the value from the time of the call, allow
		if(lastValue != part){
			return;
		}
		
		if ($.trim(part).length < 3) { return; }
	
		// get remote data as JSON
		$.getJSON(url + part, function(json){
	
			// get the total of results
			var ansLength = listTotal = json.length;
	
			// if there are results populate the results div
			if(ansLength > 0){
	
				var newData = '';
	
				// create a div for each result
				for(i=0; i < ansLength; i++) {
					newData += '<div class="unselected">' + json[i] + '</div>';
				}
	
				// update the results div
				results.html(newData);
				results.css("display","block");
				
				// for all divs in results
				var divs = $("#" +results_id+ " > div");
				
				// on mouse over clean previous selected and set a new one
				divs.live('mouseover', function() {
					divs.each(function(){ this.className = "unselected"; });
					this.className = "selected";
				});
				
				divs.click( function() {
					field.val('"'+this.childNodes[0].nodeValue+'"');
					$.clearAutoComplete(results_id);
				});
	
			} else {
				$.clearAutoComplete(results_id);
			}
		});
	}
	
	$.clearAutoComplete = function(results_id) {
		results = $('#'+results_id);
		results.html('').css("display","none");
	}
	
	$.updownArrow = function(keyCode, results, field)
	{	
		if ( keyCode == 40 || keyCode == 38 ) {
			if( keyCode == 38 ) { // keyUp
				if ( listCurrent == 0 || listCurrent == -1 ) {
					listCurrent = listTotal - 1;
				} else {
					listCurrent--;
				}
			} else { // keyDown
				if ( listCurrent == listTotal - 1 ) {
					listCurrent = 0;
				} else {
					listCurrent++;
				}
			}
			// loop through each result div applying the correct style
			results.children().each(function(i) {
				if ( i == listCurrent ) {
					field.val('"'+this.childNodes[0].nodeValue+'"');
					this.className = "selected";
				} else {
					this.className = "unselected";
				}
			});
			return true;
		} else {
			// reset
			listCurrent = -1;
			return false;
		}
	}
})(jQuery);
