/* Copyright (c) 2008 Kean Loong Tan http://www.gimiti.com/kltan
 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * Copyright notice and license must remain intact for legal use
 * jSuggest
 * Version: 1.0 (May 26, 2008)
 * Requires: jQuery 1.2.6+
 */
(function($) {

	$.fn.jSuggest = function(options) {
		// merge users option with default options
		var opts = $.extend({}, $.fn.jSuggest.defaults, options);
		var jH = ".jSuggestHover";
		var jsH = "jSuggestHover";
		var iniVal = this.value;
		var textBox = this;
		var textVal = this.value;
		var id = $(this).attr("id")
		var defVal = $(this).attr("hints") || ""
		var jC = "#jSuggestContainer-" + $(this).attr("name");

		if (!$(this).attr("value") && defVal)
			$(this).val(defVal)

		$("body").append('<div id="jSuggestContainer-' + $(this).attr("name") + '" class="jSuggestContainer"></div>');

		$(this).bind("focus", function(e) { if ($.trim(this.value) == defVal) this.value = ""; })
		$(this).bind("blur", function(e)  { if (!$.trim(this.value)) this.value = defVal; })
		$(this).bind("keydown", function(e){ if (e.keyCode == 9) $(".jSuggestContainer").hide(); })

		$(this).bind("keyup click", function(e){
			$(".jSuggestContainer").hide();
			textBox = this;
			textVal = this.value;

			if (!textVal)
				return true

			if (opts.static || this.value.length >= opts.minchar && (!defVal || $.trim(this.value)!=defVal)) {
				var offSet = $(this).offset();

				$(jC).css({
					position: "absolute",
					top: offSet.top + $(this).outerHeight() + "px",
					left: offSet.left,
					width: $(this).outerWidth()-2 + "px",
					opacity: opts.opacity,
					zIndex: opts.zindex
				}).show();

				// if escape key
				if (e.keyCode == 27 ) {
					$(jC).hide();
				}

				// if enter key
				else if (e.keyCode == 13 ) {
					if ($(jH).length == 1)
						$(textBox).val($(jH).text());
						$(jC).hide();
						iniVal = textBox.value;
						$(textBox).trigger("change")
				}
				// if down arrow
				else if (e.keyCode == 40) {
					// if any suggestion is highlighted
					if ($(jH).length == 1) {
						if (!$(jH).next().length == 0) {
							$(jH).next().addClass(jsH);
							$(".jSuggestHover:eq(0)").removeClass(jsH);
							if (opts.autoChange)
								$(textBox).val($(jH).text());
						}
					}
					else {
						$(jC + " ul li:first-child").addClass(jsH);
						if (opts.autoChange)
							$(textBox).val($(jH).text());
					}

				}

				// if up arrow
				else if (e.keyCode == 38) {
					// if any suggestion is highlighted
					if ($(jH).length == 1 ) {
						if (!$(jH).prev().length == 0) {
							$(jH).prev().addClass(jsH);
							$(".jSuggestHover:eq(1)").removeClass(jsH);
							if (opts.autoChange)
								$(textBox).val($(jH).text());
						}
						// if is first child
						else {
							$(jH).removeClass(jsH);
							$(textBox).val(iniVal);
						}
					}
				}
				// new query detected
				else {//if (textBox.value != iniVal){
					iniVal = textBox.value;
					if ($(jC + " .jSuggestLoading").length==0)
						$('<div class="jSuggestLoading"><img src="'+opts.loadingImg+'" align="bottom" /> '+ opts.loadingText+'</div>').prependTo(jC);
					else if (opts.static)
						return setTimeout(function() { $(jC).show(); }, 50)

					$(jC + " .jSuggestLoading").show();
					$(jC).find('ul').remove();

					if (textBox.timer)
						clearTimeout(textBox.timer)

					// optimize server performance by loading at intervals
					textBox.timer = setTimeout(function () {
						textBox.ondata = function() { return eval(opts.data) }
						$.ajax({
							type: opts.type,
							url: opts.url,
							data: textBox.ondata(),
							dataType: opts.dataType,
							success: function(msg){
								$(jC).find('ul').remove();
								$(jC).append(opts.formatter ? opts.formatter(msg) : msg);
								$(jC + " ul li").bind("mouseover",	function(){
										$(jH).removeClass(jsH);
										$(this).addClass(jsH);
										textVal = $(this).text();
										if (opts.autoChange)
											$(textBox).val($(jH).text());
								});
								$(jC + " ul li").click(function(){
									$(this).addClass(jsH);
									$(textBox).val(textVal);
									$(textBox).trigger("change")
								});
								$(jC + " .jSuggestLoading").hide();
							}
						});
					}, opts.static || !textBox.timer ? 10 : opts.delay);
				}
			}
			// if text is too short do nothing and hide everything
			else {
				$(jH).removeClass(jsH);
				$(jC).hide();
			}

			// no bubbling, click is binded to textBox to prevent document bind from firing
			return false;
		});

		// why no use $(this).blur ?, because jSuggest box is hidden before click fires so this is the only way to do it
		// alternate way is to say that text blur will fire before$("#jSuggestContainer ul li") click.
		$(document).bind("click", function(){
			$(".jSuggestContainer").hide();
			iniVal = textBox.value;
		});

	};

	$.fn.jSuggest.defaults = {
		minchar: 0,
		opacity: 1.0,
		zindex: 20000,
		delay: 1000,
		loadingImg: JS_BASEPATH+'/static/GUIControl/ajax-loader.gif',
		loadingText: 'Loading...',
		autoChange: false,
		url: "",
		type: "GET",
		data: "",
		static: false
	};



})(jQuery);