(function($){ /* Text field auto-completion plugin for jQuery. Based on http://www.dyve.net/jquery/?autocomplete by Dylan Verheul. */ $.suggest = function(input, url, paramName, minChars, delay) { var input = $(input).addClass("suggest").attr("autocomplete", "off"); var timeout = null; var prev = ""; var selectedIndex = -1; var results = null; input.keydown(function(e) { switch(e.keyCode) { case 27: // escape hide(); break; case 38: // up case 40: // down e.preventDefault(); if (results) { var items = $("li", results); if (!items) return; var index = selectedIndex + (e.keyCode == 38 ? -1 : 1); if (index >= 0 && index < items.length) { move(index); } } else { show(); } break; case 9: // tab case 13: // return case 39: // right if (results) { var li = $("li.selected", results); if (li.length) { select(li); e.preventDefault(); } } break; default: if (timeout) clearTimeout(timeout); timeout = setTimeout(show, delay); break; } }); input.blur(function() { if (timeout) clearTimeout(timeout); timeout = setTimeout(hide, 200); }); function hide() { if (timeout) clearTimeout(timeout); input.removeClass("loading"); if (results) { results.fadeOut("fast").remove(); results = null; } $("iframe.iefix").remove(); selectedIndex = -1; } function move(index) { if (!results) return; items = $("li", results); items.removeClass("selected"); $(items[index]).addClass("selected"); selectedIndex = index; } function select(li) { if (!li) li = $("
  • "); else li = $(li); var val = $.trim(li.text()); prev = val; input.val(val); hide(); selectedIndex = -1; } function show() { var val = input.val(); if (val == prev) return; prev = val; if (val.length < minChars) { hide(); return; } input.addClass("loading"); var params = {}; params[paramName] = val; $.get(url, params, function(data) { if (!data) { hide(); return; } if (!results) { var offset = input.offset(); results = $("
    ").addClass("suggestions").css({ position: "absolute", minWidth: input.get(0).offsetWidth + "px", top: (offset.top + input.get(0).offsetHeight) + "px", left: offset.left + "px", zIndex: 2 }).appendTo("body"); if ($.browser.msie) { var iframe = $("").insertAfter(results); setTimeout(function() { var offset = getOffset(results); iframe.css({ top: offset.top + "px", right: (offset.left + results.get(0).offsetWidth) + "px", bottom: (offset.top + results.get(0).offsetHeight) + "px", left: offset.left + "px", zIndex: 1 }); iframe.show(); }, 10); } } results.html(data).fadeTo("fast", 0.92); items = $("li", results); items .hover(function() { move(items.index(this)) }, function() { $(this).removeClass("selected") }) .click(function() { select(this); input.get(0).focus() }); move(0); }); } } $.fn.suggest = function(url, paramName, minChars, delay) { url = url || window.location.pathname; paramName = paramName || 'q'; minChars = minChars || 1; delay = delay || 400; return this.each(function() { new $.suggest(this, url, paramName, minChars, delay); }); } })(jQuery);