Saltar al contenido

Cómo resaltar texto usando javascript

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.

  1. No puede usar expresiones regulares, porque de esa manera, busca / resalta en las etiquetas html.
  2. No puede usar expresiones regulares, porque no funciona correctamente con UTF * (cualquier cosa con caracteres no latinos / ingleses).
  3. 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.

¡Haz clic para puntuar esta entrada!
(Votos: 3 Promedio: 4)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *