如何自定义格式化自动完成插件结果?

我使用的是 自动完成插件。有没有办法在下拉结果中突出显示搜索字符序列?

例如,如果我有“ foo bar”作为数据并输入“ foo”,我将在下拉列表中得到“ bar”,如下所示:

“Breakfast” appears after “Bre” is typed with “Bre” having a bold type and “akfast” having a light one.

99750 次浏览

如果你使用的是第三方插件,它有一个高亮选项: Http://docs.jquery.com/plugins/autocomplete/autocomplete#url_or_dataoptions

(见选项卡)

Autocomplete with live suggestion

是的,你可以,如果你猴子补丁自动完成。

在 jQuery UI 的 v1.8 rc3中包含的 autocomplete 小部件中,建议的弹出窗口是在 autocomplete 小部件的 _ renderMenu 函数中创建的。这个函数的定义如下:

_renderMenu: function( ul, items ) {
var self = this;
$.each( items, function( index, item ) {
self._renderItem( ul, item );
});
},

_ renderItem 函数的定义如下:

_renderItem: function( ul, item) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
},

因此,您需要做的是将 that _ renderItem fn 替换为您自己创建的产生所需效果的文件。这种重新定义库中内部函数的技术叫做 修补猴子。我是这么做的:

  function monkeyPatchAutocomplete() {


// don't really need this, but in case I did, I could store it and chain
var oldFn = $.ui.autocomplete.prototype._renderItem;


$.ui.autocomplete.prototype._renderItem = function( ul, item) {
var re = new RegExp("^" + this.term) ;
var t = item.label.replace(re,"<span style='font-weight:bold;color:Blue;'>" +
this.term +
"</span>");
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + t + "</a>" )
.appendTo( ul );
};
}

$(document).ready(...)中调用该函数一次。

现在,这是一个黑客,因为:

  • 为列表中呈现的每个项目都创建了一个 regexp obj。应该对所有项重用 regexp 对象。

  • 没有用于格式化完成的部分的 css 类。它是一个内联样式。
    这意味着如果在同一页上有多个自动完成,它们都会得到相同的处理。CSS 风格可以解决这个问题。

... 但它说明了主要的技术,它的工作,你的基本要求。

alt text

更新的工作实例: http://output.jsbin.com/qixaxinuhe


若要保留匹配字符串的大小写,而不是使用类型化字符的大小写,请使用以下代码行:

var t = item.label.replace(re,"<span style='font-weight:bold;color:Blue;'>" +
"$&" +
"</span>");

换句话说,从上面的原始代码开始,您只需要将 this.term替换为 "$&"


剪辑
以上更改了页面上的 每个自动完成小部件。如果您只想更改一个,请参阅下面的问题:
如何修补页面上仅有的一个自动补全实例?

看一下 combobox 演示,它包括结果高亮显示: http://jqueryui.com/demos/autocomplete/#combobox

那里使用的正则表达式也处理 html 结果。

这也有效:

       $.ui.autocomplete.prototype._renderItem = function (ul, item) {
item.label = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
return $("<li></li>")
.data("item.autocomplete", item)
.append("<a>" + item.label + "</a>")
.appendTo(ul);
};

@ J örn Zaefferer 和@Cheeso 的回答组合在一起。

更简单的方法,试试这个:

$('ul: li: a[class=ui-corner-all]').each (function (){
//grab each text value
var text1 = $(this).text();
//grab user input from the search box
var val = $('#s').val()
//convert
re = new RegExp(val, "ig")
//match with the converted value
matchNew = text1.match(re);
//Find the reg expression, replace it with blue coloring/
text = text1.replace(matchNew, ("<span style='font-weight:bold;color:green;'>")  + matchNew +    ("</span>"));


$(this).html(text)
});
}

非常有帮助,谢谢,+ 1。

下面是一个按照“字符串必须以术语开头”排序的简单版本:

function hackAutocomplete(){


$.extend($.ui.autocomplete, {
filter: function(array, term){
var matcher = new RegExp("^" + term, "i");


return $.grep(array, function(value){
return matcher.test(value.label || value.value || value);
});
}
});
}


hackAutocomplete();

下面的版本不需要任何正则表达式,并且匹配标签中的多个结果。

$.ui.autocomplete.prototype._renderItem = function (ul, item) {
var highlighted = item.label.split(this.term).join('<strong>' + this.term +  '</strong>');
return $("<li></li>")
.data("item.autocomplete", item)
.append("<a>" + highlighted + "</a>")
.appendTo(ul);
};

下面重复 Ted de Koning 的解决方案,其中包括:

  • 不区分大小写的搜索
  • 查找搜索字符串的多个匹配项
$.ui.autocomplete.prototype._renderItem = function (ul, item) {


var sNeedle     = item.label;
var iTermLength = this.term.length;
var tStrPos     = new Array();      //Positions of this.term in string
var iPointer    = 0;
var sOutput     = '';


//Change style here
var sPrefix     = '<strong style="color:#3399FF">';
var sSuffix     = '</strong>';


//Find all occurences positions
tTemp = item.label.toLowerCase().split(this.term.toLowerCase());
var CharCount = 0;
tTemp[-1] = '';
for(i=0;i<tTemp.length;i++){
CharCount += tTemp[i-1].length;
tStrPos[i] = CharCount + (i * iTermLength) + tTemp[i].length
}


//Apply style
i=0;
if(tStrPos.length > 0){
while(iPointer < sNeedle.length){
if(i<=tStrPos.length){
//Needle
if(iPointer == tStrPos[i]){
sOutput += sPrefix + sNeedle.substring(iPointer, iPointer + iTermLength) + sSuffix;
iPointer += iTermLength;
i++;
}
else{
sOutput += sNeedle.substring(iPointer, tStrPos[i]);
iPointer = tStrPos[i];
}
}
}
}




return $("<li></li>")
.data("item.autocomplete", item)
.append("<a>" + sOutput + "</a>")
.appendTo(ul);
};

JQueryUI1.9.0改变了 _ renderItem 的工作方式。

下面的代码考虑到了这个变化,并展示了我如何使用 Jörn Zaefferer 的 jQuery 自动完成插件进行突出显示匹配。它将在整个搜索关键词中突出显示所有单个关键词。

自从转向使用 Knokout 和 jqAuto 之后,我发现这是一种更简单的结果样式化方法。

function monkeyPatchAutocomplete() {
$.ui.autocomplete.prototype._renderItem = function (ul, item) {


// Escape any regex syntax inside this.term
var cleanTerm = this.term.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');


// Build pipe separated string of terms to highlight
var keywords = $.trim(cleanTerm).replace('  ', ' ').split(' ').join('|');


// Get the new label text to use with matched terms wrapped
// in a span tag with a class to do the highlighting
var re = new RegExp("(" + keywords + ")", "gi");
var output = item.label.replace(re,
'<span class="ui-menu-item-highlight">$1</span>');


return $("<li>")
.append($("<a>").html(output))
.appendTo(ul);
};
};


$(function () {
monkeyPatchAutocomplete();
});

这就是一个功能完整的例子:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Autocomplete - jQuery</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css">
</head>
<body>
<form id="form1" name="form1" method="post" action="">
<label for="search"></label>
<input type="text" name="search" id="search" />
</form>


<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<script>
$(function(){


$.ui.autocomplete.prototype._renderItem = function (ul, item) {
item.label = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
return $("<li></li>")
.data("item.autocomplete", item)
.append("<a>" + item.label + "</a>")
.appendTo(ul);
};




var availableTags = [
"JavaScript",
"ActionScript",
"C++",
"Delphi",
"Cobol",
"Java",
"Ruby",
"Python",
"Perl",
"Groove",
"Lisp",
"Pascal",
"Assembly",
"Cliper",
];


$('#search').autocomplete({
source: availableTags,
minLength: 3
});




});
</script>
</body>
</html>

希望这个能帮上忙

要支持多个值,只需添加以下函数:

function getLastTerm( term ) {
return split( term ).pop();
}


var t = String(item.value).replace(new RegExp(getLastTerm(this.term), "gi"), "<span class='ui-state-highlight'>$&</span>");

这是我的版本:

  • 使用 DOM 函数而不是 RegEx 来中断字符串/注入 span 标记
  • 只有指定的自动完成受到影响,而不是全部受到影响
  • 使用 UI 版本1.9. x
function highlightText(text, $node) {
var searchText = $.trim(text).toLowerCase(),
currentNode = $node.get(0).firstChild,
matchIndex,
newTextNode,
newSpanNode;
while ((matchIndex = currentNode.data.toLowerCase().indexOf(searchText)) >= 0) {
newTextNode = currentNode.splitText(matchIndex);
currentNode = newTextNode.splitText(searchText.length);
newSpanNode = document.createElement("span");
newSpanNode.className = "highlight";
currentNode.parentNode.insertBefore(newSpanNode, currentNode);
newSpanNode.appendChild(newTextNode);
}
}
$("#autocomplete").autocomplete({
source: data
}).data("ui-autocomplete")._renderItem = function (ul, item) {
var $a = $("<a></a>").text(item.label);
highlightText(this.term, $a);
return $("<li></li>").append($a).appendTo(ul);
};

突出显示匹配的文本示例

你可以使用以下代码:

自由党:

$.widget("custom.highlightedautocomplete", $.ui.autocomplete, {
_renderItem: function (ul, item) {
var $li = $.ui.autocomplete.prototype._renderItem.call(this,ul,item);
//any manipulation with li
return $li;
}
});

和逻辑:

$('selector').highlightedautocomplete({...});

它创建自定义小部件,可以覆盖 _renderItem而不覆盖原始插件原型的 _renderItem

在我的例子中还使用了一些原始的渲染函数来简化代码

如果你想在不同的地方使用不同的自动补全视图的插件,而且不想破坏你的代码,这是很重要的。