首页 文章

如何自定义格式化Autocomplete插件结果?

提问于
浏览
166

我正在使用jQuery UI Autocomplete plug-in . 有没有办法在下拉结果中突出显示搜索字符序列?

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

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

13 回答

  • 231

    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替换为您自己的创建,以产生所需的效果 . 这种技术,重新定义了库中的内部函数,我来学习的是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(...) 中调用该函数一次 .

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

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

    • 那里's no css class used for the formatting of the completed part. It'是内联样式 .
      这意味着如果您在同一页面上有多个自动填充功能,他们都会得到相同的处理 . css风格可以解决这个问题 .

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

    alt text

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


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

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

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


    EDIT
    以上内容更改了页面上的每个自动完成小部件 . 如果您只想更改一个,请看这个问题:
    How to patch just one instance of Autocomplete on a page?

  • 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örnZaefferer和@ Cheeso的回应组合 .

  • 3

    超级有帮助 . 谢谢 . 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();
    
  • 64

    在这里,一个功能完整的例子:

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

    希望这可以帮助

  • 0

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

    下面的代码考虑了这一变化,并展示了我如何使用JörnZaefferer的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();
    });
    
  • 1

    以下是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);
    };
    
  • 1

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

    $('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)
    });
      }
    
  • 8

    这是一个不需要任何正则表达式并且在标签中匹配多个结果的版本 .

    $.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);
    };
    
  • 0

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

    正在使用的正则表达式也处理html结果 .

  • 2

    这是我的版本:

    • 使用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);
    };
    

    Highlight matched text example

  • 5

    你可以使用以下代码:

    lib目录下:

    $.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 .

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

    重要的是,如果你想在不同的地方使用具有不同自动完成视图的插件,并且不想破坏你的代码 .

  • 6

    如果你改为使用第三方插件,它有一个突出显示选项:http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions

    (参见选项选项卡)

  • 1

    要支持多个值,只需添加以下功能:

    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>");
    

相关问题