My jQuery Autocomplete Mod
On a recent project I was working on, I needed an "autocomplete" form field that could do both local data array and AJAX lookups. After doing some searching, I came across Dylan Verheul's jQuery Autcomplete plug-in.
This plug-in did a lot of what I needed, but was still missing some of the functionality I required. So, I just modified the library so it worked the way I needed it to. Here's a list of the changes/enhancements I made:
- Supports local data array (can now use w/out AJAX).
- Limit dropdown to XX number of results (good for limiting the results to users)
- Autofill pre-populates text box as you type
- New findValue() method can be used to programmatically determine if the value in the box is a valid option. (Useful for verifying the text entered is an existing value option.)
- Dropdown options now correctly re-position themselves on each display (which means they adjust for changing to the DOM)
- Dropdown box defaults to the width of the input field its attached to (you can manually specify a larger width as well)
- Better emulates Windows autocomplete boxes (for example: hitting delete and retyping the same box will now bring back the dropdown menu)
- Miscellaneous bug fixes
See a live example at http://www.pengoworks.com/workshop/jquery/autocomplete.htm.
UPDATE:
jQuery v1.1.1 has a bug in the pushStack() method that causes a weird
behavior of the iFrame being populated in the text box when the
[TAB] key is pressed. See the following thread on the jQuery Mailing
List for more information:
http://www.nabble.com/Bug-in-$()-in-jQuery-v1.1.1--t3144910.html#nabble.i8718421.
You can either update your jquery.js file or pull out the latest
version from the SVN.
Comments
Connor Garvey
-
Jan 30, 2007
@
11:27 AM
Permalink
Your plugin is great (should be the best autocomplete plugin I found), but it has a little bug when used with the latest version of jquery: iframe codes will appear in the search text box when you hit `tab` while autocompleting.
also, i found that your codes can't be compressed with the dean edward javascript compressor...
tszming
-
Feb 13, 2007
@
11:46 PM
Permalink
This is actually a bug w/jQuery v1.1.1 and not with my code. The problem lies in the jQuery pushStack() method.
See the following post from the jQuery Mailing List for more information:
http://www.nabble.com/Bug-in-$()-in-jQuery-v1.1.1--t3144910.html#nabble.i8718421
Dan G. Switzer, II
-
Feb 14, 2007
@
8:48 AM
Permalink
tszming
-
Feb 14, 2007
@
9:02 AM
Permalink
you can replace the source with my function below, the problem of the original source is: even matchSubset is set to 0, your initialization will turn it into 1 anyway.
jQuery.fn.autocomplete = function(url, options, data) {
// Make sure options exists
options = typeof(options) != 'undefined' ? options : {};
// Set url as option
options.url = url;
// set some bulk local data
options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;
// Set default values for required options
options.inputClass = typeof(options.inputClass) != 'undefined' ? options.inputClass : "ac_input";
options.resultsClass = typeof(options.resultsClass) != 'undefined' ? options.resultsClass : "ac_results";
options.lineSeparator = typeof(options.lineSeparator) != 'undefined' ? options.lineSeparator : "\n";
options.cellSeparator = typeof(options.cellSeparator ) != 'undefined' ? options.cellSeparator : "|";
options.minChars = typeof(options.minChars) != 'undefined' ? options.minChars : 1;
options.delay = typeof(options.delay) != 'undefined' ? options.delay : 400;
options.matchCase = typeof(options.matchCase) != 'undefined' ? options.matchCase : 0;
options.matchSubset = typeof(options.matchSubset) != 'undefined' ? options.matchSubset : 1;
options.matchContains = typeof(options.matchContains) != 'undefined' ? options.matchContains : 0;
options.cacheLength = typeof(options.cacheLength) != 'undefined' ? options.cacheLength : 1;
options.mustMatch = typeof(options.mustMatch) != 'undefined' ? options.mustMatch : 0;
options.extraParams = typeof(options.extraParams) != 'undefined' ? options.extraParams : {};
options.loadingClass = typeof(options.loadingClass) != 'undefined' ? options.loadingClass : "ac_loading";
options.selectFirst = typeof(options.selectFirst) != 'undefined' ? options.selectFirst : false;
options.selectOnly = typeof(options.selectOnly) != 'undefined' ? options.selectOnly : false;
options.maxItemsToShow = typeof(options.maxItemsToShow) != 'undefined' ? options.maxItemsToShow : -1;
options.autoFill = typeof(options.autoFill) != 'undefined' ? options.autoFill : false;
options.width = typeof(options.width) != 'undefined' ? parseInt(options.width, 10) : 0;
this.each(function() {
var input = this;
new jQuery.autocomplete(input, options);
});
// Don't break the chain
return this;
}
tszming
-
Feb 14, 2007
@
10:27 PM
Permalink
Thank you very much,
Kevin
Kevin Chang
-
Feb 15, 2007
@
10:59 PM
Permalink
I've added a link at the bottom to download the autocomplete_ajax.cfm as a text file.
It's pretty simple--you just want the script to spit out a pipe ("|") delimited list separated by new lines. Each line is converted into an array using the pipe delimiter.
Dan G. Switzer, II
-
Feb 16, 2007
@
7:55 AM
Permalink
$("#FriendName").autocomplete(
"autofill_friends2.php",
{
delay:10,
minChars:2,
matchSubset:1,
matchContains:1,
cacheLength:10,
onItemSelect:selectItem,
onFindValue:findValue,
formatItem:formatItem,
autoFill:true
}
);
Todd Humphrey
-
Mar 11, 2007
@
1:54 AM
Permalink
You can use the extraParams option to pass in addition URL parameters to pass.
So to pass an ID of 123456, you do the following:
$("#FriendName").autocomplete(
"autofill_friends2.php",
{
delay:10,
minChars:2,
matchSubset:1,
matchContains:1,
cacheLength:10,
onItemSelect:selectItem,
onFindValue:findValue,
formatItem:formatItem,
autoFill:true,
extraParams: {"id": "123456"}
}
);
Dan G. Switzer, II
-
Mar 11, 2007
@
11:55 AM
Permalink
Randy Phillips
-
Apr 5, 2007
@
11:49 AM
Permalink
I sent this reponse to your jQuery mailing list inquiry:
http://groups.google.com/group/jquery-en/browse_fr...
Dan G. Switzer, II
-
Apr 5, 2007
@
12:40 PM
Permalink
These are replaced by ? (question mark) in the list and in the input field. I've tried to set the response to charset ISO8859-1 with no luck. The $("#myInput").val("\xd8"); does display the right character.
Any ideas?
Jens
-
Apr 12, 2007
@
3:33 AM
Permalink
I know there is a problem in the makeUrl() when sending special characters that can be fixed with:
function makeUrl(q) {
var url = options.url + "?q=" + encodeURI(q);
for (var i in options.extraParams) {
url += "&" + i + "=" + encodeURI(options.extraParams[i]);
}
return url;
};
If this doesn't fix the issue, make sure that both the page where the page where the Autocomplete plugin is and the response page both return the same charset. I'd recommend using UTF-8, just because IE tends to handle special characters better when you use that charset.
Dan G. Switzer, II
-
Apr 12, 2007
@
8:10 AM
Permalink
I'd like to give focus back to the input field and I want the plugin to be able to handle multiple entries (more or less like http://just-tech.blogspot.com/2006/12/jquery-tweak...">anjesh's tweak). How can I achieve these?
Thank you Dan.
Michael Andreas
-
Jun 6, 2007
@
3:38 AM
Permalink
This version does not support multiple values.
There is an autocomplete plug-in that's been in the works that does:
http://jqueryjs.googlecode.com/svn/trunk/plugins/a...
There are still issues that are being worked on--such as the autocomplete suggestions only work on the last entry (which means you don't get the suggestions if you're editing a 1st or 2nd values if you have 3 values in the field.)
For support for this plug-in, I suggest you post messages to the jQuery Discussion list.
Dan G. Switzer, II
-
Jun 6, 2007
@
5:08 AM
Permalink
Just to be sure, by mentioning the list you mean General Discussion list (http://groups.google.com/group/jquery-en), right? I've hit 404 when I tried to go to the jQuery Plugins List (http://jquery.com/mailman/listinfo/plugins_jquery....).
Michael Andreas
-
Jun 6, 2007
@
9:19 AM
Permalink
Yes I was referring to the General Discussion List:
http://groups.google.com/group/jquery-en
Dan G. Switzer, II
-
Jun 6, 2007
@
11:28 AM
Permalink
help with the below issue plz.
$("#location").autocompleteArray(locs);
$("#country").change( function(){
$.get("http://apps.duppi.com/ajax/", {ac: "gl", cc: $(this).fieldValue()}, function(data){
$("#location").autocompleteArray(data);
)};
I am trying to change suggestions array on #locations input on change of country SELECT element
chez
-
Aug 24, 2007
@
3:04 AM
Permalink
In the current source code, there's no way to update array. Invoking the autocompleteArray() a second time on a field will create a 2nd instance of the plugin on the field--which will cause problems.
You could add a method to update the array (you'll also want to make sure that you call the flushCache() method as well to clear) or you could use the latest mod:
http://dev.jquery.com/browser/trunk/plugins/autoco...
The version at the URL above was re-written by Jörn, with some assistance from myself.
It has a setOption() method which would allow you to update the data key with some new array data.
Dan G. Switzer, II
-
Aug 24, 2007
@
8:15 AM
Permalink
I think that Jens had the same issue as me and it was not solved with the above fix. The problem occurs with the returned data. If your server side script for instance returns:
España
Danmark
København
It would be displayed as:
Espa?a
Danmark
K?benhavn
The solution is as follows:
In your server side script encode the output with a function that encodes a string as a URL rawurlencode() if you use php.
Then change the following in autocomplete:
In the function dataToDom change the following lines so they have the unescape() function around them:
if (options.formatItem) {
li.innerHTML = unescape(options.formatItem(row, i, num));
li.selectValue = unescape(row[0]);
} else {
li.innerHTML = unescape(row[0]);
li.selectValue = unescape(row[0]);
}
If you use the autoFill you also need to unescape that like so:
$input.val($input.val() + unescape(sValue.substring(prev.length)));
Soren Beck Jensen
-
Sep 19, 2007
@
11:15 AM
Permalink
For example, if Woodstock is selected in the Ajax form, I want to populate the hidden form field with 1059.
Thanks in advance -
Stephen
Stephen Cassady
-
Oct 23, 2007
@
12:48 AM
Permalink
Just look at the code for the example of the "Ajax City Autocomplete". However instead of the following line in the findValue() function:
alert("The value you selected was: " + sValue);
You'd do something like:
$("#hiddenFieldId").val(sValue);
However, you may want to look into the updated Autocomplete code found in the jQuery SVN:
http://dev.jquery.com/browser/trunk/plugins/autoco...
Dan G. Switzer, II
-
Oct 23, 2007
@
7:09 AM
Permalink
I've set it up in my project and it works fine when testing with Firefox. But Internet Explorer refuses to even load the page. Just says "Operation aborted".
Any ideas?
whataboutthis
-
Nov 19, 2007
@
5:17 AM
Permalink
$(function(){
$('thebox').autocomplete("blah.py");
});
whataboutthis
-
Nov 19, 2007
@
5:35 AM
Permalink
whataboutthis
-
Nov 19, 2007
@
6:17 AM
Permalink
http://groups.google.com/group/jquery-en
I subscribe to the list and there are many others on the list that can help you out.
Dan G. Switzer, II
-
Nov 19, 2007
@
8:17 AM
Permalink
I was wondering if this plugin supported matching ala textmate. That is, as long as the input characters are in the right order, a match is true even if there are skpped characters. For example, if the user had type 'jm', the following would match:
12345 Jim
John Mann
4567 Ajax Money
Thanks
Jim Freeze
-
Nov 20, 2007
@
10:29 AM
Permalink
Before:
if($.browser.msie){
$results.append(document.createElement('iframe'));
}
After:
if($.browser.msie){
var iframe = document.createElement('iframe');
iframe.src="javascript:false";
$results.append(iframe);
}
Thanks
nicolas angot
-
Nov 30, 2007
@
5:24 AM
Permalink
Jim
-
Dec 28, 2007
@
3:54 PM
Permalink
Just pass in an array of arrays instead of an array of strings. This will operate just like using th pipe symbol (|) to delimit your AJAX calls.
Dan G. Switzer, II
-
Jan 3, 2008
@
4:09 PM
Permalink
I don't get the result menu after passing a value to a second autocomplete input like #autocomplete2
At #autocomplete1 I use onItemSelect:getFieldValue,
function getFieldValue(li) {
if( !!li.extra ) {
var sValue = li.extra[0];
$("#autocomplete1_hidden").val(sValue);
$("#autocomplete2").val(sValue);
$("#autocomplete2").findValue(); // not correct I think
}
}
Only when I'm using my left cursor at #autocomplete2, then I get results.
Please help!
Jacco Deen
-
Mar 25, 2008
@
8:08 AM
Permalink
I recommend you upgrade to the "official" version of the plug-in:
http://dev.jquery.com/browser/trunk/plugins/autoco...
Dan G. Switzer, II
-
Mar 25, 2008
@
1:02 PM
Permalink
Following is the code.
$("#control").autocomplete
(
url,
{
extraParams: { propertyoid : property },
delay: 750,
width: 260,
onItemSelect:function(li)
{
alert(123);
},
formatItem:function(data, i, total)
{
return data[0];
},
formatResult:function(data, i, total)
{
return data[0];
}
}
);
smitha
-
Jun 21, 2008
@
4:57 PM
Permalink
Great plug-in!
One question: how can i programmatically (through some js call) switch the functionality off? is this at all possible? i am trying to add a "turn autocomplete off" functionality to my form, but no matter what i try (removing all added attributes/classes) the autocomplete persists...
is there some switch in the function i am totally missing or is this functionality not there and once an autocomplete is created it can't be destroyed?
Thanks!
Azadi Saryev
-
Oct 3, 2008
@
5:17 AM
Permalink
There is no way to completely destroy it--at least without modifying the code. You could delete the input element and re-create it, which would remove the behavior.
Dan G. Switzer, II
-
Oct 3, 2008
@
8:35 AM
Permalink
thanks for this plugin.
I have one question: I can't figure out how to assign an "extra" value to the listed items when using the autocompleteArray function.
For example, I tried using this type of array
["Allen|1","Albert|2","Alberto|3","Alladin|4"]
specifying cellSeparator:'|' in the options but the id's are shown in the items instead of being used as extra.
What am I doing wrong?
Thanks in advance for your help Dan.
JB
JB
-
Feb 8, 2009
@
3:17 PM
Permalink
don't take my request into account, I just read that you already answered the same question to someonelse in the comments above.
For next readers, an array of array is:
[ ["Allen",1]
,["Albert",2]
,["Alberto",1]
,["Alladin",1] ]
Thanks
JB
-
Feb 8, 2009
@
6:19 PM
Permalink
One bug, though -- I have a foo.php which searches a MySQL DB and returns strings as follows, e.g. if I type "Denv" it returns "Denver Business Journal", "Denver Post", etc. This works great. However, the text inside the box reads "DenvDenver". This seems like a bug.
What did I do wrong? This behavior doesn't manifest on your example site.
Carole
-
Feb 24, 2009
@
2:40 PM
Permalink
Carole
-
Feb 24, 2009
@
2:57 PM
Permalink
function myevent(selection)
{
if (selection == "1") { pageQuartersArray = standardYears; }
if (selection == "2") { pageQuartersArray = referenceYears; }
if (selection == "3") { pageQuartersArray = referenceQuarters; }
$("#ctl00_MasterContentPlace_txtQtr1").autocompleteArray(pageQuartersArray,
{
delay:10,
minChars:1,
matchSubset:1,
onItemSelect:selectItem,
onFindValue:findValue,
autoFill:true,
maxItemsToShow:10
}
);
}
var referenceQuarters = ["0Q","-1Q","-2Q"];
var referenceYears = ["0Y","-1Y","-2Y","-3Y"];
var standardYears = ["2008Q1","2007Q4","2007Q3"];
var pageQuartersArray = ["2008Q1","2007Q4","2007Q3"];
$("#ctl00_MasterContentPlace_txtQtr1").autocompleteArray(pageQuartersArray,
{
delay:10,
minChars:1,
matchSubset:1,
onItemSelect:selectItem,
onFindValue:findValue,
autoFill:true,
maxItemsToShow:10
}
);
Justin
-
Mar 10, 2009
@
2:24 PM
Permalink
}
thanks
Justin
-
Mar 10, 2009
@
2:27 PM
Permalink
I recommend you upgrade to the "official" version of the plug-in:
http://dev.jquery.com/browser/trunk/plugins/autoco...
It offers ways to flush the cache and update the array. It's also the "official" UI version.
Dan G. Switzer, II
-
Mar 10, 2009
@
2:33 PM
Permalink
Justin
-
Mar 10, 2009
@
2:54 PM
Permalink
I was wondering if you have an example PHP script for getting the autocomplete list items from a MySQL database.
best,
Adam
-
Mar 14, 2009
@
11:10 PM
Permalink
juan felipe
-
May 10, 2009
@
6:34 PM
Permalink
I don't know why, by onItemSelect doesn't work i my code:
<code>
function getFieldValue(li) {
if( !!li.extra ) {
var sValue = li.extra[0];
alert(sValue);
}
}
$("#customer").autocomplete(
"admin/person_clients/autocomplete",
{
delay:5,
minChars:1,
matchSubset:1,
matchContains:1,
formatItem:formatItem,
onItemSelect:getFieldValue,
autoFill:true
}
);
</code>
formatItem work's.
any ideas?
Maciek
-
Jun 3, 2009
@
10:09 AM
Permalink
But i have problems with the encoding / charset. My database is in windows 1251. But it only showa "?????".
Any idea how to fix this? I read other suggestions but it doesn't really work.
Thanks in advanced!
JC
-
Jul 20, 2009
@
8:29 AM
Permalink
Sounds like your server-side scripting language isn't encoding the page correctly.
Dan G. Switzer, II
-
Jul 20, 2009
@
9:30 AM
Permalink
Regards
Steve
-
Aug 6, 2009
@
12:58 PM
Permalink
I highly recommend using the official AC plug-in:
http://bassistance.de/jquery-plugins/jquery-plugin...
It has the features you want.
Dan G. Switzer, II
-
Aug 6, 2009
@
2:21 PM
Permalink
You seem to know a lot about this AutoComplete add in. I wonder if you can help with the following issue.
From a Popup, which is a form in an IFrame, the list of selections array in an AutoComplete modified input tag on the parent form is modified. The input tag is reprocessed with Autocomplete
i.e. parent.$("#InputTagName").AutoComplete(parent.ArrayName, {})
The AutoComplete code creates a new cache and sets the correct matched sets based on the modified array but when the popup is closed only the old list is present in the parent form input tag.
I guess the new cache is associated with the current form even though the modified input tag is on the parent form.
This sounds impossible, at least with my level of understanding of Javascript, but can the parent form AutoComplete cache be modified from the child Iframe(d) form?
RobGMiller
-
Feb 3, 2011
@
1:56 PM
Permalink
My mod does not offer a way to flush the cache. The official AC plug-in that comes with the jQuery UI library I believe does--and even if it doesn't provide a method for flushing the cache, it provides ways to destroy the old behavior so you can re-attach the new behavior.
So, go grab the official AC plug-in and use that instead.
Dan G. Switzer, II
-
Feb 3, 2011
@
2:24 PM
Permalink
I did consider changing to the UI AC but felt that it might not be any better at implementing this requirement.
I'll try it..
RobGMiller
-
Feb 3, 2011
@
2:45 PM
Permalink
