Cobalt Edge

 
« Back to blog

Workaround for jQuery Autocomplete Plugin mustMatch Fail on Commas

The jQuery autocomplete plugin is quite nice, and we use it a fair bit on DealBase.  However, what I found was that if you set the mustMatch option, your text cannot contain commas, colons, and a few other punctuation (and maybe other) characters.  For some reason that I've yet to track down (debugging through many nested anonymous functions and callbacks has yet to yield an answer), it thinks it changes at some point to not think it's a match. A good example of this is if you allow a user to type in a city name, but you want to show them matching cities with the state and/or country included, to disambiguation.  E.g. you may have Portland, Oregon and Portland, Maine (not to mention the few Portlands in Australia :)

What I found fixed it for me was to set the matchSubset option to true.  This allowed it through, retaining the full text of something like "Portland, Oregon".  According to the plugin's docs, matchSubset should only come into play when using the cache, which we don't use (because we limit results to 20 items, and often there are more than 20 matches, e.g. a user types "new" or "las" or something - many cities will match).  

I'd still like to track down the real bug here, but since others have run into this, and I've yet to see any other solutions, I wanted to post that, in hopes it'll help some other person suffering from this.

Update: even setting matchSubset to true, did not solve the problem where you have a dash/hyphen in the string, and the part that matches is to the right of the dash.  Removing the dash is the only thing I've figured out to make it work.

Comments (6)

Jan 06, 2010
PR agency said...
Your blog is beautiful and comfortable,I like it.I think it is better than the former one.Really~~~
May 01, 2010
lior said...
I was wondering if by now you found a real solution.
I'm facing the same problem and can't find a fix anywhere.
May 01, 2010
Unfortunately, no. jQuery UI has now introduced an autocomplete plugin, but it really doesn't even have mustMatch at all, at least as a built-in feature (may be easily do-able with their callbacks?).
Jul 14, 2010
scubacoder said...
Hi,
I've had similar issues. My " Wal-Mart" breaks the code (notice the trailing space). Turning off the mustMatch option or removing the hyphen is not an option for my users. My solution: Php's trim() function fixed it. Hope this helps.
Mar 24, 2011
Stefan said...
Hi,
the real problem is the way autocompleter validates the match.
It sends a new request to the server with the whole text as query parameter.
And as soon as your formatted output has nothing to do with your search criteria, the result will be empty.

Example:
- you type "Portland"
- the request is like /getCities?q=portland
- the server gives back something like:
[{id: 123, value : 'Portland, Oregon'}, {id:456, value: 'Portland, Maine'}]
- if you set mustMatch:true the ac-script creates a new request after selecting id 456:
/getCities?q=portland,+maine
- this will likely be empty

You would have to fix or override the 'hideResultsNow' method

Oct 14, 2011
Jason Hoyt said...
Hi, I know this is older but I ran into this issue today myself. Finally found the correct fix for the comma issue.

The problem is the 'multiple' option. When set to true the comma should act as a separator causing whatever you type on either side of the comma to be sent back as an option. The problem is that if you look at the autocomplete source code you will notice that all of the spots in the code check to make sure the multiple:true option is in use before splitting the code. All that is except one spot.

In function trimWords you will see no check to make sure multiple:true is enabled before it just goes ahead and trims the words.

To correct this replace this:

function trimWords(value) {
if ( !value ) {
return [""];
}
var words = value.split( options.multipleSeparator );

var result = [];
$.each(words, function(i, value) {
if ( $.trim(value) )
result[i] = $.trim(value);
});
return result;
}

WITH THIS:

function trimWords(value) {
if ( !value ) {
return [""];
}
var words
if (options.multiple) {
words = value.split( options.multipleSeparator );
}
else{
words[0] = value
}
var result = [];
$.each(words, function(i, value) {
if ( $.trim(value) )
result[i] = $.trim(value);
});
return result;
}

Notice the else part that loads the single value into the array. This could easily be written to just return the trimmed value right there but doing it this way works just as well and makes it easy to make see what is happening.

I have oddly not had issues with dashes but... who knows....

Hope this helps!!!

Leave a comment...