J'utilise le plug-in de saisie semi-automatique de jQuery UI . Existe-t-il un moyen de mettre en évidence la séquence de caractères de recherche dans les résultats de la liste déroulante?
Par exemple, si j'ai "foo bar" comme donnée et que je tape "foo", j'aurai " foo bar" dans le menu déroulant, comme ça:
Oui, vous le pouvez si vous complétez automatiquement la mise à jour automatique.
Dans le widget autocomplete inclus dans la v1.8rc3 de l'interface utilisateur de jQuery, la fenêtre contextuelle de suggestions est créée 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 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, c'est remplacer _renderItem fn par votre propre création qui produit l'effet souhaité. Cette technique, qui redéfinit une fonction interne dans une bibliothèque, que j’ai appris à apprendre, s’appelle monkey-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 hack, parce que:
il y a un objet regexp créé pour chaque élément rendu dans la liste. Cette expression rationnelle obj doit être réutilisée pour tous les éléments.
il n'y a pas de classe css utilisée pour le formatage de la pièce terminée. C'est un style en ligne.
Cela signifie que si vous aviez plusieurs compléments automatiques sur la même page, ils recevraient tous le même traitement. Un style CSS résoudrait ce problème.
... mais cela illustre la technique principale, et cela fonctionne pour vos besoins de base.
exemple de travail mis à jour: http://output.jsbin.com/qixaxinuhe
Pour conserver la casse des chaînes de correspondance, par opposition à la casse des caractères saisis, 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
Par "$&"
.
[~ # ~] éditer [~ # ~]
Les modifications ci-dessus tous les widget de saisie semi-automatique de la page. Si vous voulez en changer un seul, voyez cette question:
Comment patcher * une seule * instance de saisie semi-automatique sur une page?
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 des réponses de @ Jörn Zaefferer et de @ Cheeso.
Super utile. Je vous remercie. +1.
Voici une version allégée qui effectue un tri 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();
Voilà, un exemple complet fonctionnel:
<!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>
J'espère que cela t'aides
jQueryUI 1.9.0 modifie le fonctionnement de _renderItem.
Le code ci-dessous prend en compte cette modification et montre également comment je faisais la correspondance en surbrillance à l'aide du plugin jQuery Autocomplete de Jörn Zaefferer. Il mettra en évidence tous les termes individuels dans le terme de recherche global.
Depuis que je suis passé à Knockout et jqAuto, j’ai trouvé que c’était un moyen beaucoup plus simple 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">$1</span>');
return $("<li>")
.append($("<a>").html(output))
.appendTo(ul);
};
};
$(function () {
monkeyPatchAutocomplete();
});
Voici un rappel de la solution de Ted de Koning. Il comprend :
$.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);
};
pour un moyen encore plus simple, 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 version qui ne nécessite aucune expression régulière 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);
};
Jetez un coup d’œil à la démo de combobox, elle inclut la mise en évidence des résultats: http://jqueryui.com/demos/autocomplete/#combobox
La regex utilisée ici traite également des résultats HTML.
Voici ma version:
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);
};
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 un widget personnalisé pouvant remplacer _renderItem
sans écraser _renderItem
du prototype du plugin original.
dans mon exemple, également utilisé la fonction de rendu d'origine pour simplifier le code
c'est important si vous voulez utiliser un plugin à différents endroits avec une vue différente de la saisie semi-automatique et que vous ne voulez pas casser votre code.
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>");
Si vous utilisez plutôt le plug-in tiers, il dispose d'une option de surbrillance: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions
(voir l'onglet Options)