Evidenzia una parola con jQuery


101

Fondamentalmente ho bisogno di evidenziare una parola particolare in un blocco di testo. Ad esempio, fingi di voler evidenziare la parola "dolor" in questo testo:

<p>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer dolor ullamcorper libero.
    Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>

Come posso convertire quanto sopra in qualcosa di simile:

<p>
    Lorem ipsum <span class="myClass">dolor</span> sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer <span class="myClass">dolor</span> ullamcorper
    libero. Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>

È possibile con jQuery?

Modifica : come ha sottolineato Sebastian , questo è del tutto possibile senza jQuery, ma speravo che potesse esserci un metodo speciale di jQuery che ti consentisse di eseguire selettori sul testo stesso. Sto già usando jQuery pesantemente su questo sito, quindi tenere tutto racchiuso in jQuery renderebbe le cose forse un po 'più ordinate.


Potrebbe anche interessarti: jquery.info/The-plugin-SearchHighlight
Eikern

Ehi, ho scritto un plugin che fa esattamente questo: è come il plugin di Johann Burkard mlarsen pubblicato, ma funziona con espressioni regolari invece che con stringhe. Dai un'occhiata su GitHub e fammi sapere se ci sono funzionalità aggiuntive di cui hai bisogno.

3
Nel caso avessi bisogno di una versione indulgente del plugin jQuery highlight: http://www.frightanic.com/2011/02/27/lenient-jquery-highlight-plugin-javascript/
Marcel Stör

1
Invece di evidenziare le parole con una <span>, è più corretto da usare <mark>, semanticamente parlando.
Jose Rui Santos

Ciao, sono a bordo in ritardo, ma ecco un altro frammento di codice che aiuta a evidenziare e filtrare il testo in base ai tag. Si spera che possa aiutare qualcuno jQuery Plugin per l'evidenziazione del testo e il filtraggio
Jaspreet Chahal

Risposte:


85

Prova ad evidenziare: plugin jQuery per evidenziare testo JavaScript .! Avviso: il codice sorgente disponibile in questa pagina contiene uno script di mining di criptovaluta, utilizzare il codice riportato di seguito o rimuovere lo script di mining dal download sul sito Web. !

/*

highlight v4

Highlights arbitrary terms.

<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>

MIT license.

Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>

*/

jQuery.fn.highlight = function(pat) {
 function innerHighlight(node, pat) {
  var skip = 0;
  if (node.nodeType == 3) {
   var pos = node.data.toUpperCase().indexOf(pat);
   if (pos >= 0) {
    var spannode = document.createElement('span');
    spannode.className = 'highlight';
    var middlebit = node.splitText(pos);
    var endbit = middlebit.splitText(pat.length);
    var middleclone = middlebit.cloneNode(true);
    spannode.appendChild(middleclone);
    middlebit.parentNode.replaceChild(spannode, middlebit);
    skip = 1;
   }
  }
  else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
   for (var i = 0; i < node.childNodes.length; ++i) {
    i += innerHighlight(node.childNodes[i], pat);
   }
  }
  return skip;
 }
 return this.length && pat && pat.length ? this.each(function() {
  innerHighlight(this, pat.toUpperCase());
 }) : this;
};

jQuery.fn.removeHighlight = function() {
 return this.find("span.highlight").each(function() {
  this.parentNode.firstChild.nodeName;
  with (this.parentNode) {
   replaceChild(this.firstChild, this);
   normalize();
  }
 }).end();
};

Prova anche la versione "aggiornata" dello script originale .

/*
 * jQuery Highlight plugin
 *
 * Based on highlight v3 by Johann Burkard
 * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
 *
 * Code a little bit refactored and cleaned (in my humble opinion).
 * Most important changes:
 *  - has an option to highlight only entire words (wordsOnly - false by default),
 *  - has an option to be case sensitive (caseSensitive - false by default)
 *  - highlight element tag and class names can be specified in options
 *
 * Usage:
 *   // wrap every occurrance of text 'lorem' in content
 *   // with <span class='highlight'> (default options)
 *   $('#content').highlight('lorem');
 *
 *   // search for and highlight more terms at once
 *   // so you can save some time on traversing DOM
 *   $('#content').highlight(['lorem', 'ipsum']);
 *   $('#content').highlight('lorem ipsum');
 *
 *   // search only for entire word 'lorem'
 *   $('#content').highlight('lorem', { wordsOnly: true });
 *
 *   // don't ignore case during search of term 'lorem'
 *   $('#content').highlight('lorem', { caseSensitive: true });
 *
 *   // wrap every occurrance of term 'ipsum' in content
 *   // with <em class='important'>
 *   $('#content').highlight('ipsum', { element: 'em', className: 'important' });
 *
 *   // remove default highlight
 *   $('#content').unhighlight();
 *
 *   // remove custom highlight
 *   $('#content').unhighlight({ element: 'em', className: 'important' });
 *
 *
 * Copyright (c) 2009 Bartek Szopka
 *
 * Licensed under MIT license.
 *
 */

jQuery.extend({
    highlight: function (node, re, nodeName, className) {
        if (node.nodeType === 3) {
            var match = node.data.match(re);
            if (match) {
                var highlight = document.createElement(nodeName || 'span');
                highlight.className = className || 'highlight';
                var wordNode = node.splitText(match.index);
                wordNode.splitText(match[0].length);
                var wordClone = wordNode.cloneNode(true);
                highlight.appendChild(wordClone);
                wordNode.parentNode.replaceChild(highlight, wordNode);
                return 1; //skip added node in parent
            }
        } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
                !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
                !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
            for (var i = 0; i < node.childNodes.length; i++) {
                i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
            }
        }
        return 0;
    }
});

jQuery.fn.unhighlight = function (options) {
    var settings = { className: 'highlight', element: 'span' };
    jQuery.extend(settings, options);

    return this.find(settings.element + "." + settings.className).each(function () {
        var parent = this.parentNode;
        parent.replaceChild(this.firstChild, this);
        parent.normalize();
    }).end();
};

jQuery.fn.highlight = function (words, options) {
    var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
    jQuery.extend(settings, options);

    if (words.constructor === String) {
        words = [words];
    }
    words = jQuery.grep(words, function(word, i){
      return word != '';
    });
    words = jQuery.map(words, function(word, i) {
      return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
    });
    if (words.length == 0) { return this; };

    var flag = settings.caseSensitive ? "" : "i";
    var pattern = "(" + words.join("|") + ")";
    if (settings.wordsOnly) {
        pattern = "\\b" + pattern + "\\b";
    }
    var re = new RegExp(pattern, flag);

    return this.each(function () {
        jQuery.highlight(this, re, settings.element, settings.className);
    });
};

Ci sono due soluzioni e sono contenute in un file ciascuna. Li ho aggiunti sopra. Almeno, come scenario peggiore, saranno sempre disponibili qui nella cronologia delle modifiche.
Erick Robertson

highlight v4 è un po 'buggato. C'è una correzione nella home page di Burkard: johannburkard.de/blog/programming/javascript/… In questo caso non è stata una buona idea copiare il codice qui; il collegamento punta all'ultima versione (ora :)).
Lerin Sonberg

A proposito, il tag <mark> è probabilmente migliore del tag <span> qui.
unitario

1
Se stai cercando un plugin piccolo e leggero, il plugin jquery highlight è davvero la scelta migliore. È ottimo per evidenziare e rimuovere le evidenziazioni corrispondenti al testo specificato. Se hai bisogno di espressioni regolari o altro supporto; tuttavia, controlla mark.js o qualsiasi estensione e fork per l'evidenziazione collegata a dalla pagina di evidenziazione. Uso l'evidenziazione rispetto agli altri perché la leggerezza è molto apprezzata.
Greg

3
IMPORTANTE: Johann Burkard ha incluso uno script di mining nella fonte fornita sul suo sito web !!!!!!
Lukars

42
function hiliter(word, element) {
    var rgxp = new RegExp(word, 'g');
    var repl = '<span class="myClass">' + word + '</span>';
    element.innerHTML = element.innerHTML.replace(rgxp, repl);
}
hiliter('dolor');

2
Non si desidera utilizzare innerHTML poiché è stato introdotto da Microsoft negli anni '80 e successivamente abbandonato di nuovo da Microsoft, come al solito. Anche se la maggior parte dei browser lo supporta, è tutto tranne lo standard W3C.
Steve K

21
Cosa dovresti usare al posto di innerHTML?
Kebman

15
@ Sir Ben Benji: Penso che tu stia confondendo innerHTML con innerText (l'alternativa sviluppata da Microsoft a textContent, che è davvero un anatema per le specifiche). innerHTML potrebbe essere stato avviato come un'estensione Microsoft ma in nessun modo è stato "abbandonato"; è stato supportato da tutti i principali browser sin dai primi anni 2000 e fa parte di HTML5 (già nel 2008): w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml È ancora presente negli ultimi revisione su w3.org/TR/DOM-Parsing . Vedi anche w3.org/TR/html5/references.html#refsDOMPARSING
Jay Dansand

1
Non è davvero una buona soluzione. L'ho appena usato, ma se cerco ad esempio "persona", sostituisce anche tutte le classi e gli elementi html con "persona". E anche le lettere minuscole e maiuscole non sono integrate. var rgxp = nuova RegExp ("(\\ b" + parola + "\\ b)", "gim"); risolto questo problema, ma penso che il codice non dovrebbe sostituire gli elementi html.
Richard Lindhout

33

Perché usare una funzione di evidenziazione autoprodotta è una cattiva idea

Il motivo per cui è probabilmente una cattiva idea iniziare a costruire la tua funzione di evidenziazione da zero è perché sicuramente ti imbatterai in problemi che altri hanno già risolto. Sfide:

  • Dovresti rimuovere i nodi di testo con elementi HTML per evidenziare le tue corrispondenze senza distruggere gli eventi DOM e innescare la rigenerazione DOM più e più volte (come sarebbe il caso ad esempio innerHTML)
  • Se vuoi rimuovere gli elementi evidenziati dovresti rimuovere gli elementi HTML con il loro contenuto e devi anche combinare i nodi di testo divisi per ulteriori ricerche. Ciò è necessario perché ogni plug-in di evidenziatore cerca corrispondenze all'interno dei nodi di testo e se le tue parole chiave verranno suddivise in più nodi di testo non verranno trovate.
  • Dovresti anche creare dei test per assicurarti che il tuo plugin funzioni in situazioni a cui non hai pensato. E sto parlando di test cross-browser!

Sembra complicato? Se desideri alcune funzionalità come ignorare alcuni elementi dall'evidenziazione, mappatura dei segni diacritici, mappatura dei sinonimi, ricerca all'interno di iframe, ricerca di parole separate, ecc., Questo diventa sempre più complicato.

Usa un plugin esistente

Quando usi un plugin esistente e ben implementato, non devi preoccuparti delle cose sopra nominate. L'articolo 10 plugin per evidenziatori di testo jQuery su Sitepoint mette a confronto i plugin per evidenziatori più diffusi. Ciò include plug-in di risposte a questa domanda.

Dai un'occhiata a mark.js

mark.js è un plug-in di questo tipo scritto in JavaScript puro, ma è anche disponibile come plug-in jQuery. È stato sviluppato per offrire più opportunità rispetto agli altri plugin con opzioni per:

  • cercare le parole chiave separatamente invece del termine completo
  • segni diacritici della mappa (Ad esempio se "justo" deve corrispondere anche a "justò")
  • ignora le corrispondenze all'interno degli elementi personalizzati
  • usa un elemento di evidenziazione personalizzato
  • usa la classe di evidenziazione personalizzata
  • mappare sinonimi personalizzati
  • cerca anche all'interno di iframe
  • ricevere termini non trovati

DEMO

In alternativa puoi vedere questo violino .

Esempio di utilizzo :

// Highlight "keyword" in the specified context
$(".context").mark("keyword");

// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);

È gratuito e sviluppato open-source su GitHub ( riferimento del progetto ).


11

Ecco una variazione che ignora e preserva le maiuscole:

jQuery.fn.highlight = function (str, className) {
    var regex = new RegExp("\\b"+str+"\\b", "gi");

    return this.each(function () {
        this.innerHTML = this.innerHTML.replace(regex, function(matched) {return "<span class=\"" + className + "\">" + matched + "</span>";});
    });
};

6
Funziona per il testo normale, ma non sembra escludere tag e attributi. es. Cerca "lass" quando hai un attributo di classe su un div nel tuo innerHTML.
Jonathan

Come viene richiamata questa funzione?
jiy

innerHTMLè il male, vedi la mia risposta qui. Inoltre, \\bnon funziona per i caratteri Unicode. Inoltre a questa funzione manca quasi tutto, ad esempio la ricerca all'interno di figli annidati.
amico

3

È possibile utilizzare la seguente funzione per evidenziare qualsiasi parola nel testo.

function color_word(text_id, word, color) {
    words = $('#' + text_id).text().split(' ');
    words = words.map(function(item) { return item == word ? "<span style='color: " + color + "'>" + word + '</span>' : item });
    new_words = words.join(' ');
    $('#' + text_id).html(new_words);
    }

Scegli come target l'elemento che contiene il testo, scegliendo la parola da colorare e il colore che preferisci.

Ecco un esempio :

<div id='my_words'>
This is some text to show that it is possible to color a specific word inside a body of text. The idea is to convert the text into an array using the split function, then iterate over each word until the word of interest is identified. Once found, the word of interest can be colored by replacing that element with a span around the word. Finally, replacing the text with jQuery's html() function will produce the desired result.
</div>

Utilizzo ,

color_word('my_words', 'possible', 'hotpink')

inserisci qui la descrizione dell'immagine

Azle ha anche una bella funzione per questo. Utilizza le classi, quindi assegna semplicemente un nome di classe a qualsiasi blocco di testo che desideri targetizzare.

az.style_word("target_class", target_instance, {
     "this_class" : "pink_word",
     "word" : "possible", // list any CSS styling after this line ...
     "color" : "hotpink", 
     "font-weight" : "bold"
})

2

Puoi usare il mio plugin di evidenziazione jQuiteLight , che può funzionare anche con espressioni regolari.

Per installare utilizzando il tipo npm :

npm install jquitelight --save

Per installare utilizzando il tipo di pergola :

bower install jquitelight 

Utilizzo:

// for strings
$(".element").mark("query here");
// for RegExp
$(".element").mark(new RegExp(/query h[a-z]+/));

Utilizzo più avanzato qui


@ user3631654 no che è un plugin diverso. Il mio plugin può funzionare con RegExp e ha una funzione di evidenziazione intelligente. Se hai incluso il plugin che hai menzionato prima di questo plugin, puoi ottenerlo usandovar oldMark = $.fn.mark.noConflict()
iamawebgeek

Sembra che jquery.mark abbia un metodo markRegExp()per evidenziare anche le espressioni regolari personalizzate. Quindi questo non dovrebbe essere un argomento.
user3631654

E @zazu, cosa intendi con "smart highlight"?
user3631654

@ user3631654 se attivi l'evidenziazione intelligente e passi una parola "consequnce", evidenzierà anche la parola "conseguenze" e le sue altre forme, ma se passi "il" o "bla" non ci vorrebbe "tema" o "nero"
iamawebgeek

2

JSFiddle

Usi .each(), .replace(), .html(). Testato con jQuery 1.11 e 3.2.

Nell'esempio precedente, legge la "parola chiave" da evidenziare e aggiunge il tag span con la classe "highlight". Il testo "parola chiave" è evidenziato per tutte le classi selezionate nel file .each().

HTML

<body>
   <label name="lblKeyword" id="lblKeyword" class="highlight">keyword</label>
   <p class="filename">keyword</p>
   <p class="content">keyword</p>
   <p class="system"><i>keyword</i></p>
</body>

JS

$(document).ready(function() {
   var keyWord = $("#lblKeyword").text(); 
   var replaceD = "<span class='highlight'>" + keyWord + "</span>";
   $(".system, .filename, .content").each(function() {
      var text = $(this).text();
      text = text.replace(keyWord, replaceD);
      $(this).html(text);
   });
});

CSS

.highlight {
    background-color: yellow;
}

1

È necessario ottenere il contenuto del tag p e sostituire tutti i dolor in esso con la versione evidenziata.

Non hai nemmeno bisogno di avere jQuery per questo. :-)


9
Ma è più facile con jQuery, non è vero? ;)
Eikern

7
può essere fatto con Nokia 6310, non è nemmeno necessario avere un PC per questo :-)
okliv

1

Ho scritto una funzione molto semplice che usa jQuery per iterare gli elementi che racchiudono ogni parola chiave con una classe .highlight.

function highlight_words(word, element) {
    if(word) {
        var textNodes;
        word = word.replace(/\W/g, '');
        var str = word.split(" ");
        $(str).each(function() {
            var term = this;
            var textNodes = $(element).contents().filter(function() { return this.nodeType === 3 });
            textNodes.each(function() {
              var content = $(this).text();
              var regex = new RegExp(term, "gi");
              content = content.replace(regex, '<span class="highlight">' + term + '</span>');
              $(this).replaceWith(content);
            });
        });
    }
}

Ulteriori informazioni:

http://www.hawkee.com/snippet/9854/


2
Non esegue la ricerca negli elementi nidificati, non ha alcuna funzione per rimuovere le evidenziazioni e non ha informazioni sulla licenza.
amico

Ti dispiace spiegarmi cosa significa "gi" in "new RegExp (termine," gi ")"?
vuquanghoang

0

Ho creato un repository su un concetto simile che cambia i colori dei testi i cui colori sono riconosciuti da html5 (non dobbiamo usare i valori #rrggbb effettivi e potremmo semplicemente usare i nomi come html5 standardizzati su 140 di essi)

colors.js colors.js

$( document ).ready(function() {
	
	function hiliter(word, element) {
		var rgxp = new RegExp("\\b" + word + "\\b" , 'gi'); // g modifier for global and i for case insensitive 
		var repl = '<span class="myClass">' + word + '</span>';
		element.innerHTML = element.innerHTML.replace(rgxp, repl);
			
			};

	hiliter('dolor', document.getElementById('dolor'));
});
.myClass{

background-color:red;
}
<!DOCTYPE html>
<html>
	<head>
		<title>highlight</title>
		
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
	
		 <link href="main.css" type="text/css"  rel="stylesheet"/>
		 
	</head>
	<body id='dolor'>
<p >
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer dolor ullamcorper libero.
    Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>
 <script type="text/javascript" src="main.js" charset="utf-8"></script>
	</body>
</html>


-2

È possibile ottenere questo esempio sopra:

jQuery.fn.highlight = function (str, className)
{
    var regex = new RegExp(str, "g");

    return this.each(function ()
    {
        this.innerHTML = this.innerHTML.replace(
            regex,
            "<span class=\"" + className + "\">" + str + "</span>"
        );
    });
};

non sostituire il testo all'interno di tag html come, altrimenti si rompe la pagina.


-2
$(function () {
    $("#txtSearch").keyup(function (event) {
        var txt = $("#txtSearch").val()
        if (txt.length > 3) {
            $("span.hilightable").each(function (i, v) {
                v.innerHTML = v.innerText.replace(txt, "<hilight>" + txt + "</hilight>");
            });

        }
    });
});

Jfiddle qui


hilightnon è un elemento HTML valido
user3631654

Ignora questo avviso, <hilight> è il tuo elemento personalizzato, puoi scrivere quello che vuoi. Hai visto il violino?
L.Grillo

@nickf il mio script fa esattamente la stessa cosa della risposta accettata
L.Grillo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.