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:
13 réponses
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.
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?
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.
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();
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
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();
});
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)
});
}
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);
};
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);
};
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.
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);
};
""
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.
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)
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>");