Question

J'utilise le plug-in jQuery UI Autocomplete. Est-il possible de mettre en évidence la séquence de caractères de recherche dans les résultats déroulants?

Par exemple, si je « foo bar » en tant que données et type I "toto" Je vais obtenir « foo bar » dans le menu déroulant, comme ceci:

Était-ce utile?

La solution

 Autocomplete avec la suggestion en direct

Oui, vous pouvez si vous autocomplete singe-patch.

Dans le widget autocomplete inclus dans v1.8rc3 de jQuery UI, la fenêtre contextuelle de suggestions est créé dans la fonction _renderMenu du widget autocomplete. Cette fonction est définie comme ceci:

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

La fonction _renderItem est définie comme ceci:

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

Alors ce que vous devez faire est de remplacer que _renderItem fn avec votre propre création qui produit l'effet désiré. Cette technique, redéfinir une fonction interne dans une bibliothèque, je viens d'apprendre que l'on appelle 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 );
      };
  }

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

Maintenant, c'est un hack, parce que:

  • il y a un obj regexp créé pour chaque élément rendu dans la liste. Obj regexp doit être réutilisée pour tous les articles.

  • il n'y a pas de classe utilisé pour la css mise en forme de la partie terminée. Il est un style en ligne.
    Cela signifie que si vous aviez plusieurs autocompletes sur la même page, ils avaient tous le même traitement. Un style css résoudrait cela.

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

text alt

Exemple de travail mise à jour: http://output.jsbin.com/qixaxinuhe


Pour préserver le cas des chaînes de correspondance, au lieu d'utiliser le cas des personnages typé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 original ci-dessus, il vous suffit de remplacer this.term avec "$&".


EDIT Les changements ci-dessus tous widget autocomplete sur la page. Si vous voulez changer une seule, voir cette question:
Comment patcher * juste un * instance de saisie semi-automatique sur une page?

Autres conseils

cela fonctionne aussi:

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

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

Super utile. Je vous remercie. +1.

Voici une version légère qui trie sur « String 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();

jQueryUI 1.9.0 modifie la façon dont _renderItem fonctionne.

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

Depuis son arrivée à l'aide de knock-out et jqAuto je trouve cela d'une manière beaucoup plus facile de coiffer 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">$1</span>');

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

$(function () {
   monkeyPatchAutocomplete();
});

Ici, il va, 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>$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>

Hope this helps

pour une manière 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)
});
  }

Voici une nouvelle mouture de la solution de Ted de Koning. Il comprend:

  • cas de recherche insensible
  • Trouver 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);
};

Voici une version qui ne nécessite pas d'expressions régulières et 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);
};

Jetez un oeil à la démo combobox, il comprend la mise en évidence résultat: http://jqueryui.com / démos / autocomplete / # combobox

Le regex utilisé il traite également des résultats html.

Voici ma version:

  • Utilise les fonctions DOM au lieu de RegEx pour briser les chaînes / injecter des balises span
  • Seul le autocomplete spécifié est affecté, pas tous
  • Fonctionne avec la version de l'interface utilisateur 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);
};

Mettre en surbrillance texte correspondant exemple

vous pouvez utiliser le code folowing:

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 un widget personnalisé qui peut passer outre _renderItem sans écraser _renderItem de prototype de plugin original.

dans mon exemple également utilisé la fonction d'origine à rendre un code Simplify

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

Si vous utilisez à la place le plugin 3ème partie, il a une option en surbrillance: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions

(voir l'onglet Options)

Pour prendre en charge plusieurs valeurs, ajoutez simplement 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>");
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top