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

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

例如,如果我将“foo bar”作为数据,并且键入“foo”,我会在下拉列表中获得“foo bar”,如下所示:

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


答案 1

Autocomplete with live suggestion

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

在 jQuery UI 的 v1.8rc3 中包含的自动完成小部件中,建议弹出窗口是在自动完成小部件的_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 );
},

因此,您需要做的是将_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(...)

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

  • 为列表中呈现的每个项目都创建了一个正则表达式 obj。该正则表达式 obj 应该重新用于所有项目。

  • 没有用于格式化已完成部分的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"$&"


编辑
上述内容会更改页面上的每个自动完成构件。如果您只想更改一个,请参阅此问题:
如何在页面上修补*仅一个*自动完成实例?


答案 2

这也有效:

       $.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的回应相结合。