Nuestro equipo redactor ha estado largas horas investigando para dar solución a tus dudas, te compartimos la resolución por eso esperamos serte de gran ayuda.
Solución:
Puede utilizar el efecto de resaltado de jquery.
Pero si está interesado en el código javascript sin procesar, eche un vistazo a lo que obtuve. Simplemente copie y pegue en un HTML, abra el archivo y haga clic en “resaltar”; esto debería resaltar la palabra “zorro”. En cuanto al rendimiento, creo que esto funcionaría para texto pequeño y una sola repetición (como usted especificó)
function highlight(text)
var inputText = document.getElementById("inputText");
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text);
if (index >= 0)
innerHTML = innerHTML.substring(0,index) + "" + innerHTML.substring(index,index+text.length) + "" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML;
.highlight
background-color: yellow;
The fox went over the fence
Ediciones:
Utilizando replace
Veo que esta respuesta ganó algo de popularidad, pensé que podría agregarla. También puede usar reemplazar fácilmente
"the fox jumped over the fence".replace(/fox/,"fox");
O para múltiples ocurrencias (no es relevante para la pregunta, pero se hizo en los comentarios) simplemente agregue global
en la expresión regular de reemplazo.
"the fox jumped over the other fox".replace(/fox/g,"fox");
Espero que esto ayude a los comentaristas intrigados.
Reemplazo del HTML a toda la página web
para reemplazar el HTML de una página web completa, debe consultar innerHTML
del cuerpo del documento.
document.body.innerHTML
Las soluciones que se ofrecen aquí son bastante malas.
- No puede usar expresiones regulares, porque de esa manera, busca / resalta en las etiquetas html.
- No puede usar expresiones regulares, porque no funciona correctamente con UTF * (cualquier cosa con caracteres no latinos / ingleses).
- No puede simplemente hacer un innerHTML.replace, porque esto no funciona cuando los caracteres tienen una notación HTML especial, por ejemplo
&
por &,<
para <,>
para>,ä
para,ö
para öü
para tiß
para ß, etc.
Qué necesitas hacer:
Recorra el documento HTML, busque todos los nodos de texto, obtenga el textContent
, obtenga la posición del texto resaltado con indexOf
(con un opcional toLowerCase
si no debe distinguir entre mayúsculas y minúsculas), agregue todo antes indexof
como textNode
, agregue el texto coincidente con un intervalo de resaltado y repita para el resto del nodo de texto (el resaltado string puede ocurrir varias veces en el textContent
string).
Aquí está el código para esto:
var InstantSearch =
"highlight": function (container, highlightText)
var internalHighlighter = function (options)
var id =
container: "container",
tokens: "tokens",
all: "all",
token: "token",
className: "className",
sensitiveSearch: "sensitiveSearch"
,
tokens = options[id.tokens],
allClassName = options[id.all][id.className],
allSensitiveSearch = options[id.all][id.sensitiveSearch];
function checkAndReplace(node, tokenArr, classNameAll, sensitiveSearchAll)
var nodeVal = node.nodeValue, parentNode = node.parentNode,
i, j, curToken, myToken, myClassName, mySensitiveSearch,
finalClassName, finalSensitiveSearch,
foundIndex, begin, matched, end,
textNode, span, isFirst;
for (i = 0, j = tokenArr.length; i < j; i++)
curToken = tokenArr[i];
myToken = curToken[id.token];
myClassName = curToken[id.className];
mySensitiveSearch = curToken[id.sensitiveSearch];
finalClassName = (classNameAll ? myClassName + " " + classNameAll : myClassName);
finalSensitiveSearch = (typeof sensitiveSearchAll !== "undefined" ? sensitiveSearchAll : mySensitiveSearch);
isFirst = true;
while (true)
if (finalSensitiveSearch)
foundIndex = nodeVal.indexOf(myToken);
else
foundIndex = nodeVal.toLowerCase().indexOf(myToken.toLowerCase());
if (foundIndex < 0)
if (isFirst)
break;
if (nodeVal)
textNode = document.createTextNode(nodeVal);
parentNode.insertBefore(textNode, node);
// End if (nodeVal)
parentNode.removeChild(node);
break;
// End if (foundIndex < 0)
isFirst = false;
begin = nodeVal.substring(0, foundIndex);
matched = nodeVal.substr(foundIndex, myToken.length);
if (begin)
textNode = document.createTextNode(begin);
parentNode.insertBefore(textNode, node);
// End if (begin)
span = document.createElement("span");
span.className += finalClassName;
span.appendChild(document.createTextNode(matched));
parentNode.insertBefore(span, node);
nodeVal = nodeVal.substring(foundIndex + myToken.length);
// Whend
// Next i
; // End Function checkAndReplace
function iterator(p)
if (p === null) return;
var children = Array.prototype.slice.call(p.childNodes), i, cur;
if (children.length)
for (i = 0; i < children.length; i++)
cur = children[i];
if (cur.nodeType === 3)
checkAndReplace(cur, tokens, allClassName, allSensitiveSearch);
else if (cur.nodeType === 1)
iterator(cur);
; // End Function iterator
iterator(options[id.container]);
// End Function highlighter
;
internalHighlighter(
container: container
, all:
className: "highlighter"
, tokens: [
token: highlightText
, className: "highlight"
, sensitiveSearch: false
]
); // End Call internalHighlighter
// End Function highlight
;
Entonces puedes usarlo así:
function TestTextHighlighting(highlightText)
var container = document.getElementById("testDocument");
InstantSearch.highlight(container, highlightText);
Aquí hay un documento HTML de ejemplo
Example of Text Highlight
This is a test
This is another test
äöüÄÖÜäöüÄÖÜ
Test123äöüÄÖÜ
Por cierto, si busca en una base de datos con LIKE
,
p.ej WHERE textField LIKE CONCAT('%', @query, '%')
[which you shouldn't do, you should use fulltext-search or Lucene], luego puede escapar cada carácter con y agregar una declaración-escape-SQL, de esa manera encontrará caracteres especiales que son expresiones LIKE.
p.ej
WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE ''
y el valor de @query no es '%completed%'
pero '%completed%'
(probado, funciona con SQL-Server y PostgreSQL, y cualquier otro sistema RDBMS que admita ESCAPE)
Una versión mecanografiada revisada:
namespace SearchTools
export interface IToken
token: string;
className: string;
sensitiveSearch: boolean;
export class InstantSearch
protected m_container: Node;
protected m_defaultClassName: string;
protected m_defaultCaseSensitivity: boolean;
protected m_highlightTokens: IToken[];
constructor(container: Node, tokens: IToken[], defaultClassName?: string, defaultCaseSensitivity?: boolean)
[
token: "test",
className: this.m_defaultClassName,
sensitiveSearch: this.m_defaultCaseSensitivity
];
protected checkAndReplace(node: Node)
let nodeVal: string = node.nodeValue;
let parentNode: Node = node.parentNode;
let textNode: Text = null;
for (let i = 0, j = this.m_highlightTokens.length; i < j; i++)
this.m_defaultCaseSensitivity;
let isFirst: boolean = true;
while (true)
let foundIndex: number = caseSensitive ?
nodeVal.indexOf(textToHighlight)
: nodeVal.toLowerCase().indexOf(textToHighlight.toLowerCase());
if (foundIndex < 0)
if (isFirst)
break;
if (nodeVal)
textNode = document.createTextNode(nodeVal);
parentNode.insertBefore(textNode, node);
// End if (nodeVal)
parentNode.removeChild(node);
break;
// End if (foundIndex < 0)
isFirst = false;
let begin: string = nodeVal.substring(0, foundIndex);
let matched: string = nodeVal.substr(foundIndex, textToHighlight.length);
if (begin)
textNode = document.createTextNode(begin);
parentNode.insertBefore(textNode, node);
// End if (begin)
let span: HTMLSpanElement = document.createElement("span");
if (!span.classList.contains(highlightClassName))
span.classList.add(highlightClassName);
span.appendChild(document.createTextNode(matched));
parentNode.insertBefore(span, node);
nodeVal = nodeVal.substring(foundIndex + textToHighlight.length);
// Whend
// Next i
// End Sub checkAndReplace
protected iterator(p: Node)
if (p == null)
return;
let children: Node[] = Array.prototype.slice.call(p.childNodes);
if (children.length)
for (let i = 0; i < children.length; i++)
let cur: Node = children[i];
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
if (cur.nodeType === Node.TEXT_NODE)
this.checkAndReplace(cur);
else if (cur.nodeType === Node.ELEMENT_NODE)
this.iterator(cur);
// Next i
// End if (children.length)
// End Sub iterator
public highlightNode(n:Node)
this.iterator(n);
// End Sub highlight
public highlight()
this.iterator(this.m_container);
// End Sub highlight
// End Class InstantSearch
// End Namespace SearchTools
Uso:
let searchText = document.getElementById("txtSearchText");
let searchContainer = document.body; // document.getElementById("someTable");
let highlighter = new SearchTools.InstantSearch(searchContainer, [
token: "this is the text to highlight" // searchText.value,
className: "highlight", // this is the individual highlight class
sensitiveSearch: false
]);
// highlighter.highlight(); // this would highlight in the entire table
// foreach tr - for each td2
highlighter.highlightNode(td2); // this highlights in the second column of table
Por qué usar una función de resaltado hecha por uno mismo es una mala idea
La razón por la que probablemente sea una mala idea comenzar a construir su propia función de resaltado desde cero es porque seguramente se encontrará con problemas que otros ya han resuelto. Desafíos:
- Debería eliminar los nodos de texto con elementos HTML para resaltar sus coincidencias sin destruir los eventos DOM y desencadenar la regeneración DOM una y otra vez (que sería el caso con, por ejemplo,
innerHTML
) - Si desea eliminar los elementos resaltados, deberá eliminar los elementos HTML con su contenido y también deberá combinar los nodos de texto divididos para realizar más búsquedas. Esto es necesario porque cada complemento resaltador busca coincidencias dentro de los nodos de texto y si sus palabras clave se dividirán en varios nodos de texto, no se encontrarán.
- También necesitaría crear pruebas para asegurarse de que su complemento funcione en situaciones en las que no ha pensado. ¡Y estoy hablando de pruebas entre navegadores!
¿Suena complicado? Si desea algunas funciones como ignorar algunos elementos de resaltado, mapeo de diacríticos, mapeo de sinónimos, búsqueda dentro de iframes, búsqueda de palabras separadas, etc., esto se vuelve cada vez más complicado.
Usar un complemento existente
Al usar un complemento existente y bien implementado, no tiene que preocuparse por las cosas mencionadas anteriormente. El artículo 10 complementos de resaltador de texto de jQuery en Sitepoint compara complementos de resaltador populares.
Eche un vistazo a mark.js
mark.js es un complemento escrito en JavaScript puro, pero también está disponible como complemento jQuery. Fue desarrollado para ofrecer más oportunidades que los otros complementos con opciones para:
- buscar palabras clave por separado en lugar del término completo
- diacríticos del mapa (por ejemplo, si "justo" también debe coincidir con "justò")
- ignorar coincidencias dentro de elementos personalizados
- utilizar elemento de resaltado personalizado
- usar una clase de resaltado personalizada
- sinónimos personalizados de mapas
- buscar también dentro de iframes
- recibir términos no encontrados
MANIFESTACIÓN
Alternativamente, puede ver este violín.
Ejemplo de uso:
// Highlight "keyword" in the specified context
$(".context").mark("keyword");
// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);
Es gratis y está desarrollado de código abierto en GitHub (referencia del proyecto).
Si crees que te ha sido de ayuda nuestro artículo, sería de mucha ayuda si lo compartieras con más programadores de esta forma contrubuyes a extender nuestro contenido.