Wyróżnij słowo za pomocą jQuery

W zasadzie muszę wyróżnić konkretne słowo w bloku tekstu. Na przykład udawaj, że chciałem podkreślić słowo "dolor" w tym tekście:

<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>

Jak przekonwertować powyższe na coś takiego:

<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>

Czy jest to możliwe z jQuery?

Edit: as Sebastian wskazałem , jest to całkiem możliwe bez jQuery - ale miałem nadzieję, że istnieje specjalna metoda jQuery, która pozwoli Ci zrobić selektory na samym tekście. Już używam jQuery mocno na tej stronie, więc trzymanie wszystkiego zawiniętego w jQuery sprawiłoby, że rzeczy mogą być nieco bardziej uporządkowane.

Author: Community, 2008-09-23

13 answers

Try highlight: JavaScript text higlighting jQuery plugin.

/*

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:[email protected]>

*/

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();
};

Wypróbuj również "zaktualizowaną" wersję oryginalnego skryptu .

/*
 * 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);
    });
};
 76
Author: mlarsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-21 23:12:14
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');
 38
Author: Andrew Hedges,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 11:09:26

Dlaczego używanie funkcji samorozświetlania jest złym pomysłem

Powodem, dla którego prawdopodobnie złym pomysłem jest rozpoczęcie tworzenia własnej funkcji podświetlania od zera, jest to, że z pewnością napotkasz problemy, które inni już rozwiązali. Wyzwania:

  • trzeba by usunąć węzły tekstowe z elementami HTML, aby podświetlić swoje dopasowania bez niszczenia zdarzeń DOM i wywoływania regeneracji DOM w kółko (co byłoby w przypadku np. innerHTML)
  • jeśli chcesz usunąć zaznaczone elementy, musisz usunąć elementy HTML z ich zawartością, a także połączyć dzielone węzły tekstowe do dalszych wyszukiwań. Jest to konieczne, ponieważ każda wtyczka highlighter przeszukuje węzły tekstowe w poszukiwaniu dopasowań i jeśli słowa kluczowe zostaną podzielone na kilka węzłów tekstowych, nie zostaną znalezione.
  • będziesz również musiał zbudować testy, aby upewnić się, że wtyczka działa w sytuacjach, o których nie myślałeś. Oraz Mówię o testach między przeglądarkami!
Brzmi skomplikowanie? Jeśli chcesz mieć jakieś funkcje, takie jak ignorowanie niektórych elementów z podświetlania, mapowanie znaków diakrytycznych, mapowanie synonimów, wyszukiwanie wewnątrz ramek iFrame, wyszukiwanie wyrazów oddzielonych itp. to staje się coraz bardziej skomplikowane.

Użyj istniejącej wtyczki

Używając istniejącej, dobrze zaimplementowanej wtyczki, nie musisz się martwić o powyższe rzeczy. Artykuł 10 jQuery text highlighter pluginy on Sitepoint porównuje popularne wtyczki zakreślacza. Obejmuje to wtyczki odpowiedzi z tego pytania.

Spójrz na Marka.js

Mark.js {[21] } jest taką wtyczką, która jest napisana w czystym JavaScript, ale jest również dostępna jako wtyczka jQuery. Został opracowany, aby oferować więcej możliwości niż inne wtyczki z opcjami:

  • Szukaj słów kluczowych osobno zamiast pełnego terminu
  • znaki diakrytyczne mapy (np. jeśli "justo" również mecz "justò")
  • ignoruj dopasowania wewnątrz własnych elementów
  • Użyj niestandardowego elementu podświetlania
  • użyj niestandardowej klasy podświetlania
  • niestandardowe synonimy map
  • Szukaj również wewnątrz iframes
  • receive not found terms

DEMO

Alternatywnie możesz zobaczyć to skrzypce .

Przykład użycia :

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

// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);
Jest to darmowy i rozwijany open-source na Githubie (project reference ).
 25
Author: dude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-20 10:03:08

Oto odmiana, która ignoruje i zachowuje case:

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>";});
    });
};
 11
Author: bjarlestam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-30 12:55:30

Musisz pobrać zawartość znacznika p i zastąpić wszystkie dolory w nim podświetloną wersją.

Nie musisz nawet mieć jQuery do tego. :-)

 2
Author: Sebastian Hoitz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 06:49:12

Możesz użyć my highlight plugin jQuiteLight , który może również pracować z wyrażeniami regularnymi.

Aby zainstalować za pomocą npm wpisz:

npm install jquitelight --save

Aby zainstalować za pomocą bower wpisz:

bower install jquitelight 

Użycie:

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

Bardziej zaawansowane użycie tutaj

 2
Author: iamawebgeek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-06 12:04:42

JSFiddle

Zastosowania .each (),replace (),.html (). Testowane z jQuery 1.11 i 3.2.

W powyższym przykładzie odczytuje słowo kluczowe, które ma być podświetlone i dodaje znacznik span z klasą 'highlight'. Tekst "słowo kluczowe" jest podświetlony dla wszystkich wybranych klas w .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;
}
 2
Author: Van Peer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-25 08:54:25

Napisałem bardzo prostą funkcję, która używa jQuery do iteracji elementów zawijających każde słowo kluczowe z .wyróżnij klasę.

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);
            });
        });
    }
}

Więcej informacji:

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

 1
Author: Hawkee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-21 16:12:53

Możesz użyć następującej funkcji , aby wyróżnić dowolne słowo w tekście.

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);
    }

Po prostu zaznacz element, który zawiera tekst, wybierając słowo do kolorowania i kolor do wyboru.

Oto przykład :

<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>

Użycie ,

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

Tutaj wpisz opis obrazka

 1
Author: Cybernetic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-01 01:33:58

Stworzyłem repozytorium na podobnej koncepcji, która zmienia kolory tekstów, których kolory są rozpoznawane przez html5 (nie musimy używać rzeczywistych wartości #rrggbb, a moglibyśmy używać nazw jako standaryzowanych przez html5 około 140 z nich)

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>
 0
Author: abe312,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-12 20:22:56

Jeśli naprawdę grasz, możesz przejrzeć źródło StackOverflow, aby dowiedzieć się, jak to robi podświetlanie składni na blokach kodu;)

Zasadniczo będziesz musiał dynamicznie wstawiać HTML (najlepiej zakresy) tam, gdzie ich potrzebujesz.

 -2
Author: Aaron Powell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 07:05:08

Czy można uzyskać powyższy przykład:

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>"
        );
    });
};

Aby nie zastępować tekstu wewnątrz znaczników html, to w przeciwnym razie łamie stronę.

 -2
Author: nickf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-02 12:04:50
$(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 here

 -2
Author: L.Grillo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-05 13:06:37