How are you able to get 'result' event to fire when 'multiple' is set to true and user types an entry which doesn't belong in the existing list? In my test page, I could not do it.
Anyway, I debugged through the autocomplete plugin source code and found that it doesn't handle the scenario where you have 'multiple = true', 'mustmatch = false' and user types in an entry which doesn't belong to your autocomplete list.
Here's the debugging information:
There is a code which checks for key pressed by user, if it is COMMA or your multipleSeparator, it fires the
selectCurrent() method.
// matches also semicolon
case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
case KEY.TAB:
case KEY.RETURN:
if( selectCurrent() ) {
// stop default to prevent a form submit, Opera needs special handling
event.preventDefault();
blockSubmit = true;
return false;
}
break;
This is how the selectCurrent method looks like. It tries to get currently selected value.
Here the select object is the 'autocomplete' dropdown created by the plugin.
If user has typed in a word which doesn't belong to the list, it returns false and 'result' event doesn't fire.
function selectCurrent() {
var selected = select.selected();
if( !selected ) //selected is NULL if user types in comma after typing a word which doesn't belong in the list. And that is why I was surprised that your result event was even triggered.
return false;
var v = selected.result;
previousValue = v;
if ( options.multiple ) {
var words = trimWords($input.val());
if ( words.length > 1 ) {
v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
}
v += options.multipleSeparator;
}
$input.val(v);
hideResultsNow();
$input.trigger("result", [selected.data, selected.value]);
return true;
}
To fix this, you should check for options.multiple. Here's the final code which will do the right thing:
function getLastWord()
{
var words = trimWords($input.val());
return words[words.length - 1];
};
function selectCurrent() {
var selected = select.selected();
//options.multiple BUGFIX START
//We don't have to check for options.mustMatch because the 'select' component
//already handles it.
if(! selected && options.multiple)
{
var lastWord = getLastWord();
//Below code is similar to how the Cache component generates the data.
selected = {
data : lastWord,
value : options.formatMatch(lastWord, -1, options.data.length),
result : options.formatResult && options.formatResult(lastWord) || lastWord
};
}
//options.multiple BUGFIX END
if( !selected )
return false;
var v = selected.result;
previousValue = v;
if ( options.multiple ) {
var words = trimWords($input.val());
if ( words.length > 1 ) {
v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
}
v += options.multipleSeparator;
}
$input.val(v);
hideResultsNow();
$input.trigger("result", [selected.data, selected.value]);
return true;
}
So you can modify your version of Autocomplete plugin or get the value of the textbox and do the parsing yourself.