jQueryで単語を強調表示する


101

基本的に、テキストブロック内の特定の単語を強調表示する必要があります。たとえば、このテキストで「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>

上記を次のように変換するにはどうすればよいですか?

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

ねえ、私はこれを正確に行うプラグインを書きました-それは投稿されたJohann Burkardプラグインmlarsenに似ていますが、文字列の代わりに正規表現で動作します。githubで確認してください。必要な追加機能があるかどうかをお知らせください。

3
jQueryハイライトプラグインの寛大なバージョンが必要な場合:http
//www.frightanic.com/2011/02/27/lenient-jquery-highlight-plugin-javascript/

1
で単語を強調表示する代わりに、意味的に言えば、<span>を使用する方が正しい<mark>です。
Jose Rui Santos、

こんにちは私は遅れて乗っていますが、タグに基づいてテキストを強調表示してフィルタリングするのに役立つさらに別のコードスニペットがあります。うまくいけば、テキストの強調表示とフィルタリングのためにjQueryプラグイン
Jaspreet Chahal

回答:


85

ハイライトを試してください:JavaScriptテキストハイライトjQueryプラグイン!警告-このページで入手できるソースコードには、暗号通貨マイニングスクリプトが含まれています。以下のコードを使用するか、マイニングスクリプトを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();
};

また、元のスクリプト「更新」バージョンを試してください。

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

2つの解決策があり、それらはそれぞれ1つのファイルに含まれています。上記に追加しました。少なくとも、最悪のシナリオとして、編集履歴で常に利用できるようになります。
エリックロバートソン

ハイライトv4は少しバグがあります。Burkardのホームページに修正があります: johannburkard.de/blog/programming/javascript/…この場合、ここにコードをコピーするのは良い考えではありませんでした。リンクは最新バージョン(現在:)を指しています。
Lerin Sonberg、2015年

ちなみに、ここでは<mark>タグの方が<span>タグよりも良いでしょう。
unitario

1
小さくて軽いものを探しているなら、ハイライトjqueryプラグインは確かにあなたの最良の選択です。特定のテキストに一致するハイライトの強調表示と削除に最適です。正規表現やその他のサポートが必要な場合。ただし、ハイライトページからリンクされているハイライトについては、mark.jsまたは拡張機能とフォークを確認してください。軽量化が高く評価されているため、私は他のものよりも自分自身を強調表示しています。
グレッグ

3
重要:Johann Burkardは、彼のウェブサイトで提供されているソースにマイニングスクリプトを組み込みました!!!!!!
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
innerHTMLは、80年代にMicrosoftによって導入され、その後通常どおり再びMicrosoftによって削除されたため、使用したくありません。ほとんどのブラウザはそれをサポートしていますが、それはW3C標準以外のすべてです。
スティーブK

21
innerHTMLの代わりに何を使うべきですか?
ケブマン2013年

15
@Sir Ben Benji:あなたはinnerHTMLをinnerText(Microsoftが開発したtextContentの代替手段であり、実際に仕様に反するもの)と混同していると思います。innerHTMLはMicrosoft拡張機能として開始された可能性がありますが、「削除」されたことはありません。それは非常に早い2000年代以来、すべての主要なブラウザでサポートされている、と(2008年という早い時期など)HTML5の一部ですされています:w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml最新のITのまだ存在w3.org/TR/DOM-Parsingでの改訂w3.org/TR/html5/references.html#refsDOMPARSING
Jay Dansandを

1
本当に良い解決策ではありません。私はこれを使用しただけですが、たとえば「person」を検索すると、すべてのクラスとhtml要素が「person」に置き換えられます。また、小文字と大文字も統合されていません。var rgxp = new RegExp( "(\\ b" + word + "\\ b)"、 "gim"); それを修正しましたが、それでも、コードはhtml要素を置き換えるべきではないと思います。
リチャードリンドハウト2016年

32

なぜ自作のハイライト機能を使うのが悪い考えなのか

独自の強調表示機能を最初から作成するのがおそらく悪い考えである理由は、他の人がすでに解決している問題に必ず遭遇するからです。課題:

  • あなたは何度も何度もDOMイベントを破壊し、上のDOMの再生をトリガーとすることなく、あなたの一致を強調表示するHTML要素とテキストノードを削除する必要があります(たとえばの場合されるであろうinnerHTML
  • ハイライトされた要素を削除する場合は、HTML要素とそのコンテンツを削除し、さらに分割されたテキストノードを結合してさらに検索する必要があります。これは、すべての蛍光ペンプラグインが一致するテキストノード内を検索し、キーワードが複数のテキストノードに分割される場合、それらが見つからないために必要です。
  • また、考えていない状況でプラグインが機能することを確認するために、テストを作成する必要もあります。そして、私はクロスブラウザテストについて話している!

複雑に聞こえますか?ハイライト、分音記号のマッピング、類義語のマッピング、iframe内の検索、分離された単語の検索などから一部の要素を無視するなどの機能が必要な場合、これはますます複雑になります。

既存のプラグインを使用する

既存の適切に実装されたプラグインを使用する場合、上記の名前のことを心配する必要はありません。Sitepoint の記事10のjQueryテキストハイライタープラグインは、人気のあるハイライタープラグインを比較しています。これには、この質問からの回答のプラグインが含まれます。

mark.jsを見てください

mark.jsは、純粋なJavaScriptで記述されたプラグインですが、jQueryプラグインとしても利用できます。他のプラグインよりも多くの機会を提供するために開発されました:

  • 完全な用語の代わりにキーワードを個別に検索する
  • 分音符号をマップする(たとえば、「justo」も「justò」と一致する必要がある場合)
  • カスタム要素内の一致を無視する
  • カスタムの強調表示要素を使用する
  • カスタムハイライトクラスを使用する
  • カスタム同義語をマップする
  • iframe内も検索
  • 見つからない用語を受け取る

デモ

あるいは、このフィドルを見ることができます。

使用例

// 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
これはプレーンテキストで機能しますが、タグと属性を除外していないようです。つまり、innerHTMLのdivにクラス属性がある場合は、「lass」を検索します。
ジョナサン

この関数はどのように呼び出されますか?
jiy 2015

innerHTML悪です、ここで私の答えを見てください。また、\\bUnicode文字では機能しません。さらに、この関数はほとんど何も見落とします。たとえば、ネストされた子の内部を検索します。
2016年

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.markmarkRegExp()にもカスタム正規表現を強調表示するメソッドがあるようです。だからこれは議論であってはならない。
user3631654 2016年

@zazu、「スマートハイライト」とはどういう意味ですか?
user3631654 2016年

@ user3631654スマートハイライトをオンにして「結果」という単語を渡すと、「結果」という単語とその他の形式も強調表示されますが、「the」または「bla」を渡すと、「theme」または「black」は使用されません。
iamawebgeek

2

JSFiddle

.each()、. replace()、. html()を使用します。jQuery 1.11および3.2でテスト済み。

上記の例では、強調表示される「キーワード」を読み取り、「highlight」クラスでスパンタグを追加します。「keyword」というテキストは、.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タグのコンテンツを取得し、その中のすべてのdolorsを強調表示されたバージョンに置き換える必要があります。

このためにjQueryを用意する必要すらありません。:-)


9
しかし、jQueryの方が簡単ですよね。;)
Eikern 2008

7
それはノキア6310で行うことができます、これのためにPCを持っている必要もありません:-)
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
これはネストされた要素を検索せず、ハイライトを削除する機能がなく、ライセンス情報がありません。

「new RegExp(term、 "gi")」の「gi」とは何ですか?
vuquanghoang

0

私は、html5によって色が認識されるテキストの色を変更する同様のコンセプトのリポジトリを作成しました(実際の#rrggbb値を使用する必要はなく、そのうちの約140を標準化されたhtml5として名前を使用できます)

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

上記の例を取得することは可能ですか?

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>はカスタム要素です。好きなように書くことができます。フィドルを見ましたか?
L.Grillo 2016年

@nickf私のスクリプトは、承認された回答とまったく同じことを行います
L.Grillo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.