Виділіть слово за допомогою jQuery


101

Мені в основному потрібно виділити певне слово в блоці тексту. Наприклад, зробіть вигляд, що я хотів виділити слово "долор" у цьому тексті:

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

Як перетворити вищезазначене на щось подібне:

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

Чи можливо це за допомогою jQuery?

Редагувати : Як зазначив Себастьян , це неможливо без jQuery - але я сподівався, що може існувати спеціальний метод jQuery, який дозволить вам робити селектори на сам текст. Я вже активно використовую jQuery на цьому веб-сайті, тому зберігання всього, загорнутого в jQuery, зробить речі, можливо, трохи охайнішими.


Це також може зацікавити: jquery.info/The-plugin-SearchHighlight
Ейкерн

Гей, я написав плагін, який робить саме це - це як опублікований плагін Johann Burkard mlarsen, але працює з регулярними виразами замість рядків. Перевірте це на github, і, будь ласка, повідомте мене про наявність додаткових функцій.

3
Якщо вам потрібна поблажливіша версія плагіну jQuery висвітлити: http://www.frightanic.com/2011/02/27/lenient-jquery-highlight-plugin-javascript/
Marcel Stör

1
Замість того, щоб виділяти слова з а <span>, правильніше використовувати <mark>, семантично кажучи.
Хосе Руй Сантос

Привіт, я на борту пізно, але ось ще один фрагмент коду, який допомагає виділити та фільтрувати текст на основі тегів. Сподіваємось, що комусь допоможе плагін jQuery для виділення та фільтрування тексту
Jaspreet Chahal

Відповіді:


85

Спробуйте підсвітити: підсвічування тексту JavaScript у плагіні jQuery .! Попередження - вихідний код, доступний на цій сторінці, містить скрипт видобутку криптовалюти: або скористайтеся кодом нижче, або видаліть сценарій майнінгу із завантаження на веб-сайті. !

/*

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

Спробуйте також "оновлену" версію оригінального сценарію .

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

Є два рішення, і вони містяться в одному файлі кожен. Я додав їх вище. Принаймні, як найгірший сценарій, вони завжди будуть доступні тут, в історії редагування.
Ерік Робертсон

виділити v4 трохи баггі. На домашній сторінці Burkard є виправлення: johannburkard.de/blog/programming/javascript/…. У цьому випадку не вдалося скопіювати код тут; посилання вказує на останню версію (зараз :)).
Лерін Сонберг

До речі, <mark> -таг, ймовірно, кращий, ніж тег <span> тут.
unitario

1
Якщо ви шукаєте маленький і легкий, плагін jquery - це найкращий вибір. Він чудово підкреслює та видаляє виділення, що відповідають заданому тексту. Якщо вам потрібно регулярне вираження чи інша підтримка; проте перегляньте mark.js або будь-яке з розширень та вилок для підсвітки, пов’язаних із сторінки виділення. Я використовую висвітлення себе над іншими, оскільки легка вага високо цінується.
Грег

3
ВАЖЛИВО: Йоганн Беркард включив сценарій майнінгу у джерело, яке надається на його веб-сайті !!!!!!
Лукар

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
Ви не хочете використовувати innerHTML, як це було введено Microsoft у 80-х роках, а пізніше, як завжди, Microsoft відмовилося. Незважаючи на те, що більшість браузерів підтримує це, це все, крім стандарту W3C.
Стів К

21
Що слід використовувати замість innerHTML?
Кебман

15
@ Сир Бен Бенджі: Я думаю, що ви плутаєте innerHTML з innerText (розроблена Microsoft альтернатива textContent, яка справді є анафемою специфікації). innerHTML, можливо, почався як розширення Microsoft, але жодним чином не було "скинуто"; його підтримують усі основні веб-переглядачі з самого початку 2000-х і є частиною HTML5 (ще у 2008 році): w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml Він все ще присутній в останніх редакція на w3.org/TR/DOM-Parsing . Дивіться також w3.org/TR/html5/references.html#refsDOMPARSING
Jay Dansand

1
Не дуже вдале рішення. Я просто використав це, але якщо я шукаю наприклад 'person', він також замінює всі класи та елементи html на 'person'. А малі та великі регістри також не інтегровані. var rgxp = new RegExp ("(\\ b" + слово + "\\ b)", "gim"); виправлено це, але все ж, я думаю, що код не повинен замінювати HTML-елементи.
Річард Ліндхут

32

Чому використовувати функцію саморобного виділення - погана ідея

Причина, чому, мабуть, погана ідея починати будувати власну функцію виділення з нуля - це те, що ви неодмінно зіткнетеся з проблемами, які вже вирішили інші. Виклики:

  • Вам потрібно буде видалити текстові вузли з елементами HTML, щоб виділити відповідність, не руйнуючи події DOM і не запускаючи регенерацію DOM знову і знову (що було б, наприклад, innerHTML)
  • Якщо ви хочете видалити виділені елементи, вам доведеться видалити HTML-елементи з їх вмістом, а також потрібно поєднувати розділені текстові вузли для подальшого пошуку. Це необхідно, тому що кожен плагін-маркера шукає відповідність всередині текстових вузлів, і якщо ваші ключові слова будуть розбиті на кілька текстових вузлів, вони не будуть знайдені.
  • Вам також потрібно буде скласти тести, щоб переконатися, що ваш плагін працює в ситуаціях, про які ви не думали. І я кажу про крос-браузерні тести!

Звучить складно? Якщо ви хочете отримати такі функції, як ігнорування деяких елементів від виділення, відображення діакритики, відображення синонімів, пошук всередині iframe, пошук відокремлених слів тощо, це стає все складнішим.

Використовуйте наявний плагін

Використовуючи наявний, добре реалізований плагін, вам не доведеться турбуватися про вищезазначені речі. У статті 10 плагінів для виділення тексту jQuery на Sitepoint порівнюються популярні плагіни для виділення. Сюди входять плагіни відповідей з цього питання.

Погляньте на mark.js

mark.js - такий плагін, який написаний у чистому JavaScript, але також доступний як плагін jQuery. Він був розроблений, щоб запропонувати більше можливостей, ніж інші плагіни з опціями:

  • шукати ключові слова окремо, а не повний термін
  • діакритична карта (наприклад, якщо "justo" також має відповідати "justò")
  • ігнорувати збіги всередині користувацьких елементів
  • використовувати спеціальний елемент виділення
  • використовувати спеціальний клас виділення
  • відобразити власні синоніми
  • шукати також всередині кадрів iframe
  • отримувати не знайдені умови

DEMO

Крім того, ви можете побачити цю загадку .

Приклад використання :

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

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

Це безкоштовний та розроблений відкритий код на GitHub ( посилання на проект ).


11

Ось варіант, який ігнорує та зберігає регістр:

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
Це працює для простого тексту, але, схоже, не виключає тегів та атрибутів. тобто шукайте "lass", коли у вашому внутрішньому HTMLML є атрибут класу на div.
Джонатан

Як викликається ця функція?
червня

innerHTMLце зло, дивіться мою відповідь тут. Також \\bне працює для символів unicode. Крім того, ця функція практично не вистачає, наприклад, пошук всередині вкладених дітей.
чувак

3

Ви можете використовувати наступну функцію, щоб виділити будь-яке слово у вашому тексті.

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

Просто націліть на елемент, який містить текст, вибираючи слово для розфарбовування та колір вибору.

Ось приклад :

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

Використання ,

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

введіть тут опис зображення

Azle також має приємну функцію для цього. Він використовує класи, тому просто призначте ім'я класу будь-якому тексту тексту, на який ви хочете націлити.

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

Ви можете використовувати мій плагін jQuiteLight , який також може працювати з регулярними виразами.

Щоб встановити за допомогою npm типу:

npm install jquitelight --save

Щоб встановити за допомогою типу bower :

bower install jquitelight 

Використання:

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

Більш розширене використання тут


@ user3631654 ні, це інший плагін. Мій плагін може працювати з RegExp і має функцію розумного підсвічування. Якщо ви включили плагін, про який ви згадали перед цим плагіном, ви можете отримати його за допомогоюvar oldMark = $.fn.mark.noConflict()
iamawebgeek

Схоже, на jquery.mark є метод markRegExp()також виділити власні регулярні вирази. Тому це не повинно бути аргументом.
користувач3631654

І @zazu, що ти маєш на увазі під "розумним підсвічуванням"?
користувач3631654

@ user3631654 Якщо увімкнути розумну підсвітку та передати слово "наслідком", воно також підкреслить слово "наслідки" та інші його форми, але якщо ви передасте "" чи "бла", воно не сприймає "тему" чи "чорну"
iamawebgeek

2

JSFiddle

Використовує .each (), .replace (), .html (). Перевірено за допомогою jQuery 1.11 та 3.2.

У наведеному вище прикладі читається "ключове слово", яке слід виділити, і додає тег "span" класом "виділити". Текст "ключове слово" виділяється для всіх обраних класів у .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

Потрібно отримати вміст тегу p і замінити всі долори в ньому на виділену версію.

Для цього вам навіть не потрібно мати jQuery. :-)


9
Але з jQuery простіше, чи не так? ;)
Ейкерн

7
це можна зробити з nokia 6310, для цього вам навіть не потрібно мати ПК :-)
okliv

1

Я написав дуже просту функцію, яка використовує jQuery для ітерації елементів, що обгортають кожне ключове слово класом .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);
            });
        });
    }
}

Більше інформації:

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


2
Це не пошук у вкладених елементах, не має функції для видалення виділень і не має ліцензійної інформації.
чувак

Ви не проти пояснити мені, що таке "gi" у "новому RegExp (термін," gi ")"?
vuquanghoang

0

Я створив сховище за подібною концепцією, яка змінює кольори текстів, кольори яких розпізнаються html5 (нам не доведеться використовувати фактичні значення #rrggbb, а можна просто використовувати імена як html5, стандартизованих приблизно на 140 з них)

color.js color.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

Чи можна отримати цей вище приклад:

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

не замінюючи текст всередині html-тегів типу, це в іншому випадку порушує сторінку.


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


hilightне є дійсним HTML-елементом
user3631654

Просто ігноруйте це попередження, <hilight> - ваш власний елемент, ви можете писати все, що завгодно. Ви бачили скрипку?
Л.Грілло

@nickf мій сценарій роблять точно так само, як і прийнятої відповіді
Л.Грілло
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.