Używam wtyczki jQuery UI Autocomplete . Czy istnieje sposób wyróżnienia sekwencji znaków wyszukiwania w rozwijanych wynikach?
Na przykład, jeśli mam „foo bar” jako dane i wpiszę „ foo ”, w menu rozwijanym pojawi się „ foo bar”, na przykład:
Używam wtyczki jQuery UI Autocomplete . Czy istnieje sposób wyróżnienia sekwencji znaków wyszukiwania w rozwijanych wynikach?
Na przykład, jeśli mam „foo bar” jako dane i wpiszę „ foo ”, w menu rozwijanym pojawi się „ foo bar”, na przykład:
Odpowiedzi:
Tak, możesz, jeśli automatycznie uzupełniasz małpy.
W widgecie autouzupełniania zawartym w wersji 1.8rc3 interfejsu użytkownika jQuery wyskakujące okienko sugestii jest tworzone w funkcji _renderMenu widżetu autouzupełniania. Ta funkcja jest zdefiniowana w następujący sposób:
_renderMenu: function( ul, items ) {
var self = this;
$.each( items, function( index, item ) {
self._renderItem( ul, item );
});
},
Funkcja _renderItem jest zdefiniowana w następujący sposób:
_renderItem: function( ul, item) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
},
Musisz więc zastąpić _renderItem fn własną kreacją, która daje pożądany efekt. Technika ta, redefiniująca wewnętrzną funkcję w bibliotece, której nauczyłem się, nazywa się małpą łataniem . Oto jak to zrobiłem:
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 );
};
}
Wywołaj tę funkcję raz w $(document).ready(...)
.
To jest hack, ponieważ:
istnieje wyrażenie regularne obj. utworzone dla każdego elementu wyświetlanego na liście. To wyrażenie regularne obj powinno zostać ponownie użyte dla wszystkich pozycji.
nie ma klasy css używanej do formatowania ukończonej części. To styl inline.
Oznacza to, że jeśli masz wiele autouzupełniania na tej samej stronie, wszystkie zostaną potraktowane tak samo. Styl CSS rozwiązałby ten problem.
... ale ilustruje główną technikę i działa zgodnie z Twoimi podstawowymi wymaganiami.
zaktualizowany przykład roboczy: http://output.jsbin.com/qixaxinuhe
Aby zachować wielkość liter w pasujących łańcuchach, zamiast używać wielkości liter w wpisywanych znakach, użyj tej linii:
var t = item.label.replace(re,"<span style='font-weight:bold;color:Blue;'>" +
"$&" +
"</span>");
Innymi słowy, zaczynając od oryginalnego kodu powyżej, wystarczy zastąpić this.term
go "$&"
.
EDYTUJ
Powyższe zmienia wszystkie widżety autouzupełniania na stronie. Jeśli chcesz zmienić tylko jedną, zobacz to pytanie:
Jak załatać * tylko jedną * instancję autouzupełniania na stronie?
var re = new RegExp(this.term, "i");
Świetny post!
to też działa:
$.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);
};
połączenie odpowiedzi @ Jörn Zaefferer i @ Cheeso.
$().autocomplete()
Super pomocny. Dziękuję Ci. +1.
Oto uproszczona wersja z sortowaniem „Ciąg musi zaczynać się od terminu”:
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();
Oto pełny, funkcjonalny przykład:
<!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>
Mam nadzieję że to pomoże
jQueryUI 1.9.0 zmienia sposób działania _renderItem.
Poniższy kod bierze pod uwagę tę zmianę, a także pokazuje, jak robiłem dopasowywanie podświetlenia za pomocą wtyczki jQuery Autocomplete Jörna Zaefferera. Podświetli wszystkie poszczególne terminy w ogólnym wyszukiwaniu.
Odkąd zacząłem używać Knockout i jqAuto, stwierdziłem, że jest to znacznie łatwiejszy sposób na stylizowanie wyników.
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();
});
.jqAutocompleteMatch { font-weight: bold; }
this.term
Przed wykonaniem jakiegokolwiek przetwarzania należy użyć logiki ucieczki przed wyrażeniem regularnym for. Zobacz Escape string for use in JavaScript regex jako jedną z wielu odpowiedzi, jak to zrobić.
aby uzyskać jeszcze łatwiejszy sposób, spróbuj tego:
$('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)
});
}
Oto powtórzenie rozwiązania Teda de Koninga. Obejmuje:
$.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);
};
Oto wersja, która nie wymaga żadnych wyrażeń regularnych i pasuje do wielu wyników na etykiecie.
$.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);
};
Spójrz na demo combobox, zawiera wyróżnianie wyników: http://jqueryui.com/demos/autocomplete/#combobox
Używane tam wyrażenie regularne dotyczy również wyników html.
Oto moja wersja:
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);
};
możesz użyć następującego kodu:
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;
}
});
i logika:
$('selector').highlightedautocomplete({...});
tworzy niestandardowy widget, który może zastąpić oryginalny prototyp wtyczki _renderItem
bez nadpisywania _renderItem
.
w moim przykładzie wykorzystałem również oryginalną funkcję renderującą do uproszczenia kodu
jest to ważne, jeśli chcesz używać wtyczki w różnych miejscach z innym widokiem autouzupełniania i nie chcesz łamać kodu.
Jeśli zamiast tego użyjesz wtyczki innej firmy, ma ona opcję podświetlenia: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions
(patrz zakładka Opcje)