/** * Json key/value autocomplete for jQuery * Provides a transparent way to have key/value autocomplete * Copyright (C) 2008 Ziadin Givan www.CodeAssembly.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see http://www.gnu.org/licenses/ * * Examples * $("input#example").autocomplete("autocomplete.php");//using default parameters * $("input#example").autocomplete("autocomplete.php",{minChars:3,timeout:3000,validSelection:false,parameters:{'myparam':'myvalue'},before : function(input,text) {},after : function(input,text) {}}); * minChars = Minimum characters the input must have for the ajax request to be made * timeOut = Number of miliseconds passed after user entered text to make the ajax request * validSelection = If set to true then will invalidate (set to empty) the value field if the text is not selected (or modified) from the list of items. * parameters = Custom parameters to be passed * after, before = a function that will be caled before/after the ajax request */ jQuery.fn.autocomplete = function(url, settings ) { return this.each( function()//do it for each matched element { //this is the original input var textInput = $(this); //create a new hidden input that will be used for holding the return value when posting the form, then swap names with the original input textInput.after('').attr("name", textInput.attr("name") + "_text"); var valueInput = $(this).next(); //create the ul that will hold the text and values valueInput.after(''); var list = valueInput.next().css({top: textInput.offset().top + textInput.outerHeight(), left: textInput.offset().left, width: textInput.width()}); var oldText = ''; var typingTimeout; var size = 0; var selected = 0; settings = jQuery.extend(//provide default settings { minChars : 1, timeout: 1000, after : null, before : null, validSelection : true, parameters : {'inputName' : valueInput.attr('name'), 'inputId' : textInput.attr('id')} } , settings); function getData(text) { window.clearInterval(typingTimeout); if (text != oldText && (settings.minChars != null && text.length >= settings.minChars)) { clear(); if (settings.before == "function") { settings.before(textInput,text); } textInput.addClass('autocomplete-loading'); settings.parameters.text = text; $.getJSON(url,settings.parameters,function(data) { var items = ''; if (data) { size = data.length; for (i = 0; i < data.length; i++)//iterate over all options { for ( key in data[i] )//get key => value { items += '
  • ' + data[i][key].replace(new RegExp("(" + text + ")","i"),"$1") + '
  • '; } list.html(items); //on mouse hover over elements set selected class and on click set the selected value and close list list.show().children(). hover(function() { $(this).addClass("selected").siblings().removeClass("selected");}, function() { $(this).removeClass("selected") } ). click(function () { valueInput.val( $(this).attr('value') );textInput.val( $(this).text() ); clear(); }); } if (settings.after == "function") { settings.after(textInput,text); } } textInput.removeClass('autocomplete-loading'); }); oldText = text; } } function clear() { list.hide(); size = 0; selected = 0; } textInput.keydown(function(e) { window.clearInterval(typingTimeout); if(e.which == 27)//escape { clear(); } else if (e.which == 46 || e.which == 8)//delete and backspace { clear(); //invalidate previous selection if (settings.validSelection) valueInput.val(''); } else if(e.which == 13)//enter { if ( list.css("display") == "none")//if the list is not visible then make a new request, otherwise hide the list { getData(textInput.val()); } else { clear(); } e.preventDefault(); return false; } else if(e.which == 40 || e.which == 9 || e.which == 38)//move up, down { switch(e.which) { case 40: case 9: selected = selected >= size - 1 ? 0 : selected + 1; break; case 38: selected = selected <= 0 ? size - 1 : selected - 1; break; default: break; } //set selected item and input values textInput.val( list.children().removeClass('selected').eq(selected).addClass('selected').text() ); valueInput.val( list.children().eq(selected).attr('value') ); } else { //invalidate previous selection if (settings.validSelection) valueInput.val(''); typingTimeout = window.setTimeout(function() { getData(textInput.val()) },settings.timeout); } }); }); };