Comment puis-je personnaliser les résultats du plug-in Autocomplete?

j'utilise le jQuery UI Autocomplete plug-in . Y a-t-il un moyen de mettre en évidence la séquence de caractères de recherche dans les résultats du menu déroulant?

par exemple, si j'ai "foo bar" Comme données et que je tape "foo" je vais obtenir " foo bar "dans le menu déroulant, comme ceci:

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

161
demandé sur Xufox 2010-03-13 00:18:46

13 réponses

Autocomplete with live suggestion

Oui, vous pouvez si vous le singe-patch de saisie semi-automatique.

dans le widget autocomplete inclus dans v1.8rc3 de jQuery UI, le popup de suggestions est créé dans la fonction _renderMenu du widget autocomplete. Cette fonction est définie comme suit:

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

la fonction _renderItem est définie comme suit:

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

Donc ce que vous devez faire est de remplacer ce _renderItem fn par votre propre création qui produit l'effet désiré. Cette technique, redéfinissant une fonction interne dans une bibliothèque, je suis venu pour apprendre est appelé singe-patching . Voici comment je l'ai fait:

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

appelez cette fonction une fois dans $(document).ready(...) .

maintenant, c'est un piratage, parce que:

  • il y a un objet regexp créé pour chaque élément rendu dans la liste. Ce regexpobj devrait être réutilisé pour tous les articles.

  • aucune classe css n'est utilisée pour le formatage de la partie remplie. C'est un style en ligne.

    Cela signifie que si vous aviez plusieurs autocomplètes sur la même page, ils auraient tous le même traitement. Un style css résoudrait.

...mais il illustre la technique principale, et il fonctionne pour vos besoins de base.

alt text

mise à jour de l'exemple de travail: http://output.jsbin.com/qixaxinuhe


pour préserver le cas des chaînes de correspondance, plutôt que d'utiliser le cas des caractères dactylographiés, utilisez cette ligne:

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

en d'autres termes, à partir du code d'origine ci-dessus, vous avez juste besoin de remplacer this.term par "$&" .


modifier

Les changements ci-dessus chaque widget autocomplete sur la page. Si vous voulez en changer un seul, voyez cette question:

comment Patcher *juste une * instance D'Autocomplete sur une page?

229
répondu Cheeso 2017-06-27 14:37:12

cela fonctionne aussi:

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

une combinaison de réponses de @Jörn Zaefferer et @Cheeso.

62
répondu Raj 2010-08-11 11:29:09

super utile. Remercier. +1.

Ici est une version light qui trie sur "Chaîne doit commencer par le terme":

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();
8
répondu orolo 2011-04-20 20:43:43

voici, un exemple fonctionnel complet:

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

Espérons que cette aide

6
répondu Fabio Nolasco 2017-07-24 10:18:23

jQueryUI 1.9.0 change how _renderItem works.

le code ci-dessous prend ce changement en considération et montre aussi comment je faisais surligner l'appariement à l'aide du plugin jQuery Autocomplete de Jörn Zaefferer. Il mettra en évidence tous les termes individuels dans le terme de recherche globale.

depuis le passage à L'utilisation Knockout et jqAuto j'ai trouvé cette façon beaucoup plus facile de styliser les résultats.

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"></span>');

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

$(function () {
   monkeyPatchAutocomplete();
});
5
répondu 79IT 2014-05-04 05:24:36

pour un chemin encore plus facile, essayez ceci:

$('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)
});
  }
3
répondu Aaron 2010-08-27 20:57:36

voici une relecture de la solution de Ted De Koning. Il comprend:

  • recherche insensible à la casse
  • recherche de nombreuses occurrences de la chaîne recherchée
$.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);
};
3
répondu Pierre 2012-08-25 03:22:57

Voici une version qui ne nécessite pas d'expressions régulières et qui correspond à plusieurs résultats dans l'étiquette.

$.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);
};
2
répondu Ted de Koning 2011-12-08 13:55:32

regardez la démo de combobox, elle inclut la mise en évidence des résultats: http://jqueryui.com/demos/autocomplete/#combobox

le regex en cours d'utilisation il traite également des résultats html.

1
répondu Jörn Zaefferer 2010-04-04 22:56:21

voici ma version:

  • utilise des fonctions DOM au lieu de RegEx pour briser les chaînes/injecter des balises de portée
  • seul l'autocomplète spécifiée est affectée, pas tous les
  • fonctionne avec la version 1.9 de L'interface utilisateur.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);
};

""
1
répondu Salman A 2014-01-28 08:13:45

vous pouvez utiliser le code suivant:

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

et logique:

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

il crée widget personnalisé qui peut remplacer _renderItem sans réécriture _renderItem de prototype de plugin original.

dans mon exemple a également utilisé la fonction de rendu d'origine pour simplifier le code

il est important si vous voulez utiliser le plugin dans différents endroits avec différents vue de la saisie semi-automatique et ne voulez pas casser votre code.

1
répondu E.Monogarov 2016-05-16 18:39:20

si vous utilisez plutôt le plugin tiers, il a une option de surbrillance: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions

(voir l'onglet Options)

0
répondu Brian Luft 2010-03-12 21:26:14

pour supporter des valeurs multiples, il suffit d'ajouter la fonction suivante:

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>");
0
répondu ZaieN 2013-12-09 03:05:53