jquery UI自动完成支持是否限制在支持多个值的无效值上键入?

我正在接管一个新的网站,它使用了一个旧的弃用版本的jquery autocomplete插件 。 我试图使用最新的jquery ui自动完成function重新创建function,并且有一个function我似乎无法复制。

我想在有多个值允许的情况下复制“mustMatch”function。

所以基本上,如果我开始输入任何未显示在任何搜索结果中的测试(甚至是部分字符串搜索),它会重置该字段的条目(而不是让我输入不在有效列表中的垃圾)选择)

那么就说我的名单(本地)是{“Bird”,“Song”,“Happy”}

它会让我输入

Bird, Son 

但如果我在之后键入z它会保持打开状态

  Bird, Son 

告诉我这是一个无效的条目

这可以在jquery ui自动完成中执行吗?

我看到很多来自谷歌的旧post提出了类似的问题和答案 ,但是没有一个似乎与多个值一起工作(许多似乎根本不工作:()

您可以使用这种代码段:

{我在这里使用keyup事件进行检查,但在现代浏览器中,您可以使用输入(oninput)事件或绑定onpaste事件}

http://jsfiddle.net/q2SSF/

  var availableTags = [ "Bird", "Son", "Happy"]; function split(val) { return val.split(/,\s*/); } function checkAvailable(term) { var length = term.length, chck = false, term = term.toLowerCase(); for (var i = 0, z = availableTags.length; i < z; i++) if (availableTags[i].substring(0, length).toLowerCase() === term) return true; return false; } function extractLast(term) { return split(term).pop(); } var $autocomplete = $("#autocomplete") // don't navigate away from the field on tab when selecting an item .on("keydown", function (event) { if (event.keyCode === $.ui.keyCode.TAB && $(this).data("ui-autocomplete").menu.active) { event.preventDefault(); } }) .on("keyup", function (event) { var ac_value = this.value; if (!checkAvailable(extractLast(ac_value))) this.value = ac_value.substring(0, ac_value.length - 1); }) .autocomplete({ minLength: 0, source: function (request, response) { // delegate back to autocomplete, but extract the last term response($.ui.autocomplete.filter( availableTags, extractLast(request.term))); }, focus: function () { // prevent value inserted on focus return false; }, select: function (event, ui) { var terms = split(this.value); // remove the current input terms.pop(); // add the selected item terms.push(ui.item.value); // add placeholder to get the comma-and-space at the end terms.push(""); this.value = terms.join(", "); return false; } }); 

我大多是从jQuery UI复选的例子中复制过的,但做了一些改动。 目标是完全按照您描述的方式工作,并且这可以处理任何输入方法:附加到字符串,插入字符串,以及复制和粘贴。

修改多个示例的两个键可以满足您的需求,其中创建自定义filter并添加到源方法。 最初我改变了搜索方法,但是来源让我更多地控制了如何显示选项(实现最小长度并在最后一个术语被修剪后继续显示)。

当执行源方法时,它似乎在各种输入类型(打字,粘贴,剪切)期间被触发,我分割输入并检查每个输入的有效性。 我检查每个因为如果有人粘贴了文本,那么中间的某些内容可能会在之前有效的地方变为无效。 在最后一个术语之前的任何内容都会在最后一个元素应用了从开始filter时应用精确filter。 最后一个术语也被区别对待,因为它被修剪到不匹配的输入发生的点。

之后,如果发生任何更改,我会更新输入值。 然后我考虑minLength值显示对lastTerm的响应,即使是最初的多个例子也忘记了。

我相信我的解决方案是最好的,因为它处理所有输入方法,并且很简单,因为它只添加了原始示例中的一个函数。 一个缺点是,为了保持解决方案简单而产生了一些效率低下的问题,但这些效率很小,以至于不会引起任何明显的性能影响。

其他想法 :另一个想法是,将拆分正则表达式更改为/,?\ s * / /以便逗号是可选的。 在我的测试中,在每次响应后输入空格是很自然的。 另一种方法是每次更新输入值,使逗号间距保持一致。

的jsfiddle

 var availableTags = ['Bird', 'Song', 'Happy']; function split(val) { return val.split(/,\s*/); } // removes the last term from the array, and adds newValue if given function removeLastTerm(val, newValue) { var terms = split(val); terms.pop(); if (newValue) { terms.push(newValue); } terms.push(''); return terms.join(', ');; } // filter from start position from: // http://blog.miroslavpopovic.com/jqueryui-autocomplete-filter-words-starting-with-term function filterFromStart(array, term) { var matcher = new RegExp('^' + $.ui.autocomplete.escapeRegex(term), 'i'); return $.grep(array, function (value) { return matcher.test(value.label || value.value || value); }); } function filterExact(array, term) { var matcher = new RegExp('^' + $.ui.autocomplete.escapeRegex(term) + '$', 'i'); return $.grep(array, function (value) { return matcher.test(value.label || value.value || value); }); } $('#tags') // don't navigate away from the field on tab when selecting an item .bind('keydown', function (event) { if (event.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active) { event.preventDefault(); } }) .autocomplete({ minLength: 0, delay: 0, source: function (request, response) { var terms = split(request.term), lastTrimmed = false, lastTerm, originalMaxIndex = terms.length - 1, filteredMaxIndex; if (originalMaxIndex >= 0) { // remove any terms that don't match exactly for (var i = originalMaxIndex - 1; i >= 0; i--) { if (filterExact(availableTags, terms[i]).length == 0) { terms.splice(i, 1); } } filteredMaxIndex = terms.length - 1; // trim the last term until it matches something or is emty lastTerm = terms[filteredMaxIndex]; while (lastTerm.length != 0 && filterFromStart(availableTags, lastTerm).length == 0) { lastTerm = lastTerm.substr(0, lastTerm.length - 1); lastTrimmed = true; } if (lastTrimmed) { // add modified LastTerm or reduce terms array if (lastTerm.length == 0) { terms.splice(filteredMaxIndex--, 1); terms.push(''); } else terms[filteredMaxIndex] = lastTerm; } if (filteredMaxIndex >= 0) { // only execute if we've removed something if (filteredMaxIndex < originalMaxIndex || lastTrimmed) { this.element.val(terms.join(', ')); } } else { this.element.val(request.term); } if (this.options.minLength <= lastTerm.length) { response(filterFromStart(availableTags, lastTerm)); } else { response([]); } } else { response(filterFromStart(availableTags, '')); } }, focus: function () { // prevent value inserted on focus return false; }, select: function (event, ui) { // add the selected value to the input. this.value = removeLastTerm(this.value, ui.item.value); return false; } });