Ich verwende das jQuery UI Autocomplete-Plug-in . Gibt es eine Möglichkeit, die Suchzeichenfolge in Dropdown-Ergebnissen hervorzuheben?
Wenn ich beispielsweise "foo bar" als Daten habe und "foo" eingebe, wird in der Dropdown-Liste " foo bar" angezeigt. so was:
Ja, das kannst du, wenn du das Affen-Patch automatisch vervollständigst.
In dem in Version 1.8rc3 der jQuery-Benutzeroberfläche enthaltenen Widget für die automatische Vervollständigung wird das Popup der Vorschläge in der Funktion _renderMenu des Widgets für die automatische Vervollständigung erstellt. Diese Funktion ist folgendermaßen definiert:
_renderMenu: function( ul, items ) {
var self = this;
$.each( items, function( index, item ) {
self._renderItem( ul, item );
});
},
Die Funktion _renderItem ist folgendermaßen definiert:
_renderItem: function( ul, item) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
},
Sie müssen also das _renderItem fn durch Ihre eigene Kreation ersetzen, die den gewünschten Effekt erzeugt. Diese Technik, mit der ich eine interne Funktion in einer Bibliothek neu definiert habe, heißt monkey-patching . So habe ich es gemacht:
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 );
};
}
Rufen Sie diese Funktion einmal in $(document).ready(...)
auf.
Das ist ein Hack, weil:
für jedes Element in der Liste wird ein regulärer Ausdruck erstellt. Dieses Regexp-Objekt sollte für alle Elemente wiederverwendet werden.
für die Formatierung des fertigen Teils wird keine CSS-Klasse verwendet. Es ist ein Inline-Stil.
Das bedeutet, wenn Sie mehrere Autovervollständigungen auf derselben Seite hatten, würden sie alle die gleiche Behandlung erhalten. Ein CSS-Stil würde das lösen.
... aber es zeigt die Haupttechnik und entspricht Ihren Grundanforderungen.
aktualisiertes Arbeitsbeispiel: http://output.jsbin.com/qixaxinuhe
Verwenden Sie diese Zeile, um die Groß- und Kleinschreibung der Übereinstimmungszeichenfolgen beizubehalten, anstatt die Groß- und Kleinschreibung der eingegebenen Zeichen zu verwenden:
var t = item.label.replace(re,"<span style='font-weight:bold;color:Blue;'>" +
"$&" +
"</span>");
Mit anderen Worten, beginnend mit dem obigen Originalcode müssen Sie nur this.term
Durch "$&"
Ersetzen.
[~ # ~] edit [~ # ~]
Die obigen Änderungen every Widget auf der Seite automatisch vervollständigen. Wenn Sie nur einen ändern möchten, sehen Sie sich diese Frage an:
Wie kann * nur eine * Instanz von Autocomplete auf einer Seite gepatcht werden?
das funktioniert auch:
$.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);
};
eine Kombination aus @ Jörn Zaefferer und @ Cheesos Antworten.
Super hilfsbereit Vielen Dank. +1.
Hier ist eine Light-Version, die nach "String muss mit dem Begriff beginnen" sortiert ist:
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();
Hier ist ein funktionierendes vollständiges Beispiel:
<!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>
Hoffe das hilft
jQueryUI 1.9.0 ändert die Funktionsweise von _renderItem.
Der folgende Code berücksichtigt diese Änderung und zeigt auch, wie ich mit dem jQuery Autocomplete-Plugin von Jörn Zaefferer das Highlight-Matching durchgeführt habe. Es werden alle einzelnen Begriffe im gesamten Suchbegriff hervorgehoben.
Seit ich Knockout und jqAuto benutze, ist es mir viel leichter gefallen, die Ergebnisse zu stylen.
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();
});
Hier ist eine Wiederholung von Ted de Konings Lösung. Es enthält :
$.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);
};
versuchen Sie es noch einfacher:
$('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)
});
}
Hier ist eine Version, die keine regulären Ausdrücke erfordert und mit mehreren Ergebnissen in der Bezeichnung übereinstimmt.
$.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);
};
Schauen Sie sich die Combobox-Demo an. Sie enthält die Hervorhebung der Ergebnisse: http://jqueryui.com/demos/autocomplete/#combobox
Der dort verwendete reguläre Ausdruck behandelt auch HTML-Ergebnisse.
Hier ist meine 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);
};
sie können folgenden Code verwenden:
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;
}
});
und Logik:
$('selector').highlightedautocomplete({...});
es erstellt ein benutzerdefiniertes Widget, das _renderItem
überschreiben kann, ohne _renderItem
des ursprünglichen Plugin-Prototyps zu überschreiben.
in meinem Beispiel wurde auch die ursprüngliche Renderfunktion verwendet, um den Code zu vereinfachen
es ist wichtig, dass Sie das Plugin an verschiedenen Stellen mit unterschiedlicher Ansicht der Autovervollständigung verwenden und Ihren Code nicht beschädigen möchten.
Um mehrere Werte zu unterstützen, fügen Sie einfach folgende Funktion hinzu:
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>");
Wenn Sie stattdessen das Plugin eines Drittanbieters verwenden, gibt es eine Hervorhebungsoption: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions
(siehe Registerkarte Optionen)