javascript - ejemplo - jquery autocomplete select event
¿Cómo puedo personalizar el formato de los resultados del complemento Autocompletar? (13)
Estoy usando el complemento Autocompletar de jQuery UI . ¿Hay alguna manera de resaltar la secuencia de caracteres de búsqueda en los resultados desplegables?
Por ejemplo, si tengo "foo bar" como datos y escribo "foo" obtendré " foo bar" en el menú desplegable, como este:
Aquí está mi versión:
- Utiliza funciones DOM en lugar de RegEx para romper cadenas / etiquetas de extensión de inyección
- Solo el autocompletado especificado se ve afectado, no todos
- Funciona con UI versión 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);
};
Aquí hay una repetición de la solución de Ted de Koning. Incluye :
- Búsqueda insensible a mayúsculas
- Encontrar muchas apariciones de la cadena buscada
$.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);
};
Aquí hay una versión que no requiere expresiones regulares y coincide con múltiples resultados en la etiqueta.
$.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);
};
Aquí va, un completo ejemplo funcional:
<!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>
Espero que esto ayude
Eche un vistazo a la demostración de combobox, incluye el resaltado de resultados: http://jqueryui.com/demos/autocomplete/#combobox
La expresión regular en uso allí también se ocupa de los resultados html.
Para admitir valores múltiples, simplemente agregue la siguiente función:
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>");
Súper útil. Gracias. +1.
Aquí hay una versión ligera que ordena "La cadena debe comenzar con el término":
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();
Si en cambio usa el complemento de terceros, tiene una opción destacada: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions
(ver la pestaña de Opciones)
esto también funciona:
$.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);
};
una combinación de las respuestas de @Jörn Zaefferer y @ Cheeso.
jQueryUI 1.9.0 cambia cómo funciona _renderItem.
El siguiente código tiene en cuenta este cambio y también muestra cómo estaba haciendo la coincidencia de resaltado usando el complemento JQuery Autocomplete de Jörn Zaefferer. Resaltará todos los términos individuales en el término de búsqueda general.
Desde que comencé a usar Knockout y jqAuto, encontré esta forma mucho más sencilla de diseñar los resultados.
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();
});
para una manera aún más fácil, intente esto:
$(''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)
});
}
puedes usar el siguiente código:
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;
}
});
y lógica:
$(''selector'').highlightedautocomplete({...});
crea un widget personalizado que puede anular _renderItem
sin sobreescribir _renderItem
del prototipo de complemento original.
en mi ejemplo también usé la función de renderización original para simplificar el código
Es importante que quiera usar el complemento en diferentes lugares con diferentes vistas de autocompletar y no quiera romper su código.
Sí, puedes si tu mono-parche se autocompleta.
En el widget de autocompletar incluido en v1.8rc3 de jQuery UI, la ventana emergente de sugerencias se crea en la función _renderMenu del widget de autocompletar. Esta función se define así:
_renderMenu: function( ul, items ) {
var self = this;
$.each( items, function( index, item ) {
self._renderItem( ul, item );
});
},
La función _renderItem se define así:
_renderItem: function( ul, item) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
},
Entonces, lo que debes hacer es reemplazar ese _renderItem fn con tu propia creación que produzca el efecto deseado. Esta técnica, redefinir una función interna en una biblioteca, he aprendido que se llama monkey-patching . Así es como lo hice:
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 );
};
}
Llame a esa función una vez en $(document).ready(...)
.
Ahora, esto es un truco, porque:
hay un obj regexp creado para cada elemento presentado en la lista. Ese obje regexp debe ser reutilizado para todos los artículos.
no hay clase css utilizada para el formateo de la parte completa. Es un estilo en línea.
Esto significa que si tuviera múltiples autocompletos en la misma página, todos recibirían el mismo tratamiento. Un estilo css resolvería eso.
... pero ilustra la técnica principal, y funciona para sus requisitos básicos.
ejemplo de trabajo actualizado: http://output.jsbin.com/qixaxinuhe
Para preservar el caso de las cadenas de coincidencias, en lugar de usar el caso de los caracteres escritos, use esta línea:
var t = item.label.replace(re,"<span style=''font-weight:bold;color:Blue;''>" +
"$&" +
"</span>");
En otras palabras, a partir del código original anterior, solo necesita reemplazar this.term
con "$&"
.
EDITAR
Lo anterior cambia cada widget de autocompletar en la página. Si quiere cambiar solo uno, vea esta pregunta:
Cómo parchear * solo una * instancia de Autocompletar en una página?