Как я могу настроить формат результатов подключаемого модуля автозаполнения?

StackOverflow https://stackoverflow.com/questions/2435964

Вопрос

я использую Плагин автозаполнения jQuery UI.Есть ли способ выделить последовательность символов поиска в раскрывающихся результатах?

Например, если у меня есть данные «foo bar» и я набираю «foo», я получу «фу bar» в раскрывающемся списке, вот так:

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

Это было полезно?

Решение

Autocomplete with live suggestion

Да, вы можете, если вы используете автозаполнение обезьяны.

В виджете автозаполнения, включенном в версию 1.8rc3 пользовательского интерфейса jQuery, всплывающее окно с предложениями создается в функции _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(...) .

Это хак, потому что:

  • для каждого элемента, отображаемого в списке, создается объект регулярного выражения.Этот объект регулярного выражения следует повторно использовать для всех элементов.

  • для форматирования завершенной части не используется класс 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 с "$&".


РЕДАКТИРОВАТЬ
Вышеуказанные изменения каждый виджет автозаполнения на странице.Если вы хотите изменить только один, см. этот вопрос:
Как исправить *только один* экземпляр автозаполнения на странице?

Другие советы

это также работает:

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

Супер полезно.Спасибо.+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();

jQueryUI 1.9.0 меняет принцип работы _renderItem.

Код ниже учитывает это изменение, а также показывает, как я выполнял сопоставление выделенных участков с помощью плагина 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();
});

Вот полный функциональный пример:

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

Надеюсь это поможет

для еще более простого способа попробуйте следующее:

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

Вот перефразирование решения Теда де Конинга.Оно включает :

  • Поиск без учета регистра
  • Поиск множества вхождений искомой строки
$.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);
};

Вот версия, которая не требует каких-либо регулярных выражений и соответствует нескольким результатам в метке.

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

Взгляните на демонстрацию комбобокса, она включает в себя подсветку результатов: http://jqueryui.com/demos/autocomplete/#combobox

Используемое там регулярное выражение также имеет дело с результатами HTML.

Вот моя версия:

  • Использует функции DOM вместо RegEx для разрыва строк/вставки тегов диапазона.
  • Затрагивается только указанное автозаполнение, а не все
  • Работает с версией пользовательского интерфейса 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 оригинального прототипа плагина.

в моем примере также использовалась оригинальная функция рендеринга для упрощения кода

это важно, если вы хотите использовать плагин в разных местах с разным представлением автозаполнения и не хотите нарушать свой код.

Если вместо этого вы используете сторонний плагин, у него есть опция выделения:http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions

(см. вкладку «Параметры»)

Для поддержки нескольких значений просто добавьте следующую функцию:

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>");
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top