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

IT技术 javascript jquery jquery-ui jquery-ui-autocomplete
2021-02-06 23:21:26

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

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

“Breakfast”出现在“Bre”之后,“Bre”为粗体,“akfast”为浅体。

6个回答

使用实时建议自动完成

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

在 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 替换为您自己的创作,从而产生所需的效果。这种在库中重新定义内部函数的技术,我是来学习的,叫做monkey-patching这是我如何做到的:

  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 样式可以解决这个问题。

...但它说明了主要技术,它适用于您的基本要求。

替代文字

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


要保留匹配字符串的大小写,而不是使用键入字符的大小写,请使用以下行:

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

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


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

我要说的一件事是,如果您希望将匹配字符串的任何部分(不仅仅是开头)中的结果加粗,请将 RegExp 行修改为: var re = new RegExp(this.term) ;
2021-03-11 23:21:26
非常感谢你!如果这成为 jQuery UI 的一部分,那就太棒了。
2021-03-12 23:21:26
JQueryUI 自动完成似乎默认进行不区分大小写的搜索,因此在 RegExp 对象中添加“i”标志是有意义的。正如@DavidRyder 所提到的,也没有理由在正则表达式中使用“^”。喜欢: var re = new RegExp(this.term, "i"); 好帖子!
2021-04-02 23:21:26
谢谢奇索。你有这个 jsbin 链接吗?
2021-04-03 23:21:26
请注意,如果您将事情串联起来,重置上下文很重要: oldFn.apply(this, [ul, item]);
2021-04-06 23:21:26

这也有效:

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

@RNKushwaha 在你打电话之前的任何地方 $().autocomplete()
2021-03-12 23:21:26
我更喜欢这个,因为它匹配整个词。
2021-03-21 23:21:26
这很好用。唯一需要注意的是 item.label 正在被替换。对我来说,我的文本框中收到了“<strong...”。只需将替换结果分配给另一个变量即可清除。如果您的数据包含放入文本框中的 value 属性,则不会出现此问题。
2021-03-21 23:21:26
如果您有支持多个值的自动完成功能,这将不起作用。有什么建议?
2021-04-06 23:21:26
在自动完成结果中突出显示文本的最简单方法。显然要注意上面 leora 和 Kijana 指出的错误
2021-04-07 23:21:26

超级有帮助。谢谢你。+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();
谢谢 Orolo,我在多个位置使用自动完成功能,并想要一个中心位置,我可以在其中进行更改以仅显示以键入的字符开头的结果,而这正是我所需要的!
2021-04-07 23:21:26
谢谢。这是最好的解决方案。它适用于不区分大小写的情况。
2021-04-09 23:21:26

这是一个功能完整的示例:

<!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>

希望这可以帮助

jQueryUI 1.9.0 改变了 _renderItem 的工作方式。

下面的代码考虑了这一变化,并展示了我是如何使用 Jörn Zaefferer 的 jQuery Autocomplete 插件进行高亮匹配的。它将突出显示整个搜索词中的所有单个词。

自从开始使用 Knockout 和 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();
});
@IdanShechter 很棒的评论。this.term在进行任何处理之前,应该使用一些逻辑来转义for regex。请参阅Escape string for use in Javascript regex作为如何执行此操作的众多答案之一。
2021-03-24 23:21:26
当我搜索像 '(' 这样的字符时,它会导致错误(“Uncaught SyntaxError: Invalid regular expression: /(sam|at|()/: Unterminated group”)无论如何通过防止与正则表达式冲突来解决这个问题?
2021-03-31 23:21:26
很棒的答案!喜欢它突出显示术语,无论它们出现在哪里。很酷。感谢您更新帖子。我确实遇到的一个问题是关于您使用的 .ui-menu-item-highlight 类。这是由 jquery-ui 还是消费者定义的?我更改了类名以适应我自己的方式,并简单地将字体粗细设为粗体。 .jqAutocompleteMatch { font-weight: bold; }
2021-04-04 23:21:26