2010-07-20 10 views
17

Estoy intentando escribir un "cuadro de búsqueda de sugerencias" y no puedo encontrar una solución que permita resaltar una subcadena con javascript manteniendo el estuche original.Javascript: resaltar subcadena manteniendo el estuche original pero buscando en modo insensible a mayúsculas

Por ejemplo si yo busque "ca" Busco lado del servidor en un modo de mayúsculas y minúsculas y no tengo los siguientes resultados:

Calculadora

calendario

ESCAPE

lo haría desea ver la cadena de búsqueda en todas las palabras anteriores, por lo que el resultado debería ser:

Ca lculator

ca lendar

ES CA PE

Probé con el siguiente código:

reg = new RegExp(querystr, 'gi'); 
final_str = 'foo ' + result.replace(reg, '<b>'+querystr+'</b>'); 
$('#'+id).html(final_str); 

Pero, obviamente, de esta manera me suelta el caso original!

¿Hay alguna manera de resolver este problema?

Respuesta

41

Utilice una función para el segundo argumento para .replace() que devuelve la cadena coincidente real con las etiquetas concatenadas.

Pruébelo:http://jsfiddle.net/4sGLL/

reg = new RegExp(querystr, 'gi'); 
     // The str parameter references the matched string 
     // --------------------------------------v 
final_str = 'foo ' + result.replace(reg, function(str) {return '<b>'+str+'</b>'}); 
$('#' + id).html(final_str);​ 

jsFiddle Ejemplo con de entrada:https://jsfiddle.net/pawmbude/

+8

mejor manera de hacerlo esto, aunque lo haría sin una función: 'result.replace (reg, '$ &')'. Aunque no sé nada sobre el rendimiento, parece más agradable. – Joost

+0

la __ solución perfecta__ –

+0

Yo tampoco, pero siempre me olvido de la sintaxis de 'función ', así que busqué documentación. Encontré esto por 'accidente'. – Joost

0

Hago exactamente lo mismo.

Necesita hacer una copia.

Guardo en el archivo db una copia de la cadena real, en minúsculas.

Luego busco usando una versión minúscula de la cadena de consulta o hago una expresión regular insensible a mayúsculas y minúsculas.

Luego use el índice de inicio encontrado resultante en la cadena principal, más la longitud de la cadena de consulta, para resaltar la cadena de consulta dentro del resultado.

No puede usar la cadena de consulta en el resultado ya que su caso no está determinado. Debe resaltar una parte de la cadena original.

-1

.match() realiza caso a juego insensible y devuelve una matriz de los partidos con el caso intacto.

var matches = str.match(queryString), 
    startHere = 0, 
    nextMatch, 
    resultStr ='', 
    qLength = queryString.length; 

for (var match in matches) { 
    nextMatch = str.substr(startHere).indexOf(match); 
    resultStr = resultStr + str.substr(startHere, nextMatch) + '<b>' + match + '</b>'; 
    startHere = nextMatch + qLength; 
} 
-1

He encontrado la manera más fácil de lograrlo.La expresión regular de JavaScript recuerda la cadena con la que coincide. Esta característica se puede usar aquí.

He modificado el código un poco.

reg = new RegExp("("+querystr.trim()+")", 'gi'); 
final_str = 'foo ' + result.replace(reg, "<b>&1</b>"); 
$('#'+id).html(final_str); 
+0

¿puede agregar alguna descripción sobre la diferencia entre su solución y la respuesta aceptada? y la utilidad del ")"? – Mimouni

0

buenos resultados con

function str_highlight_text(string, str_to_highlight){ 
    var reg = new RegExp(str_to_highlight, 'gi'); 
    return string.replace(reg, function(str) {return '<span style="background-color:#ffbf00;color:#fff;"><b>'+str+'</b></span>'}); 
} 

y más fácil de recordar ... THX a user113716: https://stackoverflow.com/a/3294644/2065594

0

Mientras que las otras respuestas hasta ahora parecen simples, que no se puede utilizar realmente en muchos casos del mundo real, ya que no manejan el escaneo de HTML de texto correcto y el escape de RegExp. Si desea resaltar cada posible fragmento, mientras que escapar el texto correctamente, una función como la que podría devolver todos los elementos que debe agregar a su buzón de sugerencias:

function highlightLabel(label, term) { 
    if (!term) return [ document.createTextNode(label) ] 
    const regex = new RegExp(term.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi') 
    const result = [] 
    let left, match, right = label 
    while (match = right.match(regex)) { 
    const m = match[0], hl = document.createElement('b'), i = match.index 
    b.innerText = m 
    left = right.slice(0, i) 
    right = right.slice(i + m.length) 
    result.push(createTextNode(left), hl) 
    if (!right.length) return result 
    } 
    result.push(createTextNode(right)) 
    return result 
} 
1

ES6 versión

const highlight = (needle, haystack) => 
    haystack.replace(new RegExp(needle, 'gi'), str => `<strong>${str} 
</strong>`) 
Cuestiones relacionadas