JavaScriptを使用してテキストを強調表示する方法


98

誰かがWebページ上のテキストを強調表示できるJavaScript関数を手伝ってくれませんか。そして、要件は-検索の場合のようにテキストのすべての出現箇所を強調表示するのではなく、一度だけ強調表示することです。


4
関数のコードを投稿していただければ、お手伝いします。あなたにそのような関数を作成するように私たちに依頼した場合...それはあまりありません。あなたは自分で何かをしなければなりません。何かを始めて、行き詰まったときに戻ってきます。
Felix Kling、2011

7
はい私は「質問の仕方」を読みました、そして私は自分で何かをしましたが、行き詰まったので私は尋ねました。私はAndroidで作業していますが、javasriptについてほとんど知識がありません。そのため、自分でそれを行うことができません。以前は別のJavaScriptを使用していましたが、特定の制限はありませんでした。この質問をしている間、私は正しい言葉を使っていなかったかもしれません、そしてそれを申し訳ありませんが、それ以外のことを考えないでください。
Ankit

1
このプラグインはあなたに興味があるかもしれません:github.com/julmot/jmHighlight。キーワードを個別にまたは用語として強調表示したり、カスタム要素やクラス名との一致を強調表示したり、発音区別符号を検索したりできます。さらに、一致を検索するコンテキストをフィルタリングできます。

1
次の正規表現の方法でチェックアウト... stackoverflow.com/a/45519242/2792959

私はそれについてここに記事を用意しました、exhesham.com / 2017/11/20 /…
Hesham Yassin

回答:


100

jquery ハイライト効果を使用できます。

しかし、生のjavascriptコードに興味がある場合は、私が得たものを見てください。単にHTMLに貼り付けてコピーし、ファイルを開いて[強調表示]をクリックします。これにより、「fox」という単語が強調表示されます。パフォーマンスの点で、これは小さなテキストと1回の繰り返し(指定したような)に効果があると思います

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) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
   inputText.innerHTML = innerHTML;
  }
}
.highlight {
  background-color: yellow;
}
<button onclick="highlight('fox')">Highlight</button>

<div id="inputText">
  The fox went over the fence
</div>

編集:

使用する replace

この回答が人気を博したのを見て、私はそれを追加するかもしれないと思った。交換も簡単に使用できます

"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");

または、複数のオカレンス(質問には関係ありませんが、コメントで尋ねられた場合)の場合globalは、replace正規表現を追加するだけです。

"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");

これが興味をそそられるコメンターに役立つことを願っています。

HTMLをWebページ全体に置き換える

Webページ全体のHTMLを置き換えるにinnerHTMLは、ドキュメントの本文を参照する必要があります。

document.body.innerHTML


返信ありがとうございます
。JavaScript

あなたは置き換えることができ"<span class='highlight'>""<span style='color: " + color + ";'>"、色のようなものでなければなりませんvar color = "#ff0000";
Yaniro

ページ全体で単語のすべての出現箇所を強調表示したい場合はどうなりますか?@guy mograbi
Baqer Naqvi

4
単純な「置換」を使用することは悪い考えです。私はなぜここに説明してきました:stackoverflow.com/a/32758672/3894981

2
HTMLタグ/属性などを強調表示しようとするため、これは良いアイデアではありません。たとえば、次のような場合はどうなりますか <img src="fox.jpg" /> ?次のような無効なHTMLが表示されます:<img src="<span class='highlight'>fox</span>.jpg" /> 良くない
dcporter7

46

ここで提供されるソリューションはかなり悪いです。

  1. 正規表現は使用できません。これは、htmlタグで検索/強調表示するためです。
  2. 正規表現はUTF *(ラテン文字/英語以外の文字を含むもの)では適切に機能しないため、使用できません。
  3. これは、文字が特殊なHTML表記を使用している場合は機能しないためです。たとえば&amp;&lt;for 、for、<、&gt;for、&auml;ä、&ouml;ö &uuml;、ö &szlig;、ß、ü などです。

するべきこと:

HTMLドキュメントをループし、すべてのテキストノードを見つけ、取得textContent、とハイライトテキストの位置を取得しますindexOf(オプションでtoLowerCase、それは大文字と小文字を区別しない場合)、前アペンドすべてindexofとしてtextNodeハイライトスパンとマッチしたテキストを追加し、そして、残りのテキストノードについて繰り返します(ハイライト文字列はtextContent文字列内で複数回出現する可能性があります)。

これのコードは次のとおりです。

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

};

その後、次のように使用できます。

function TestTextHighlighting(highlightText)
{
    var container = document.getElementById("testDocument");
    InstantSearch.highlight(container, highlightText);
}

ここにHTMLドキュメントの例があります

<!DOCTYPE html>
<html>
    <head>
        <title>Example of Text Highlight</title>
        <style type="text/css" media="screen">
            .highlight{ background: #D3E18A;}
            .light{ background-color: yellow;}
        </style>
    </head>
    <body>
        <div id="testDocument">
            This is a test
            <span> This is another test</span>
            äöüÄÖÜäöüÄÖÜ
            <span>Test123&auml;&ouml;&uuml;&Auml;&Ouml;&Uuml;</span>
        </div>
    </body>
</html>

ちなみに、データベースでを使用して検索する場合LIKE
たとえば、WHERE textField LIKE CONCAT('%', @query, '%')[これを行うべきではありません。フルテキスト検索またはLuceneを使用する必要があります]なら、\ですべての文字をエスケープし、SQLエスケープステートメントを追加できます。 LIKE式である特殊文字が見つかります。

例えば

WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'

そして@queryの値ではありません'%completed%'が、'%\c\o\m\p\l\e\t\e\d%'

(テスト済み、SQL-ServerとPostgreSQL、およびESCAPEをサポートする他のすべてのRDBMSシステムで動作します)


改訂されたtypescript-version:

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)
        {
            this.iterator = this.iterator.bind(this);
            this.checkAndReplace = this.checkAndReplace.bind(this);
            this.highlight = this.highlight.bind(this);
            this.highlightNode = this.highlightNode.bind(this);    

            this.m_container = container;
            this.m_defaultClassName = defaultClassName || "highlight";
            this.m_defaultCaseSensitivity = defaultCaseSensitivity || false;
            this.m_highlightTokens = tokens || [{
                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++)
            {
                let curToken: IToken = this.m_highlightTokens[i];
                let textToHighlight: string = curToken.token;
                let highlightClassName: string = curToken.className || this.m_defaultClassName;
                let caseSensitive: boolean = curToken.sensitiveSearch || 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 

使用法:

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

正解です。この方法はやり過ぎに見えますが、簡潔です。結果は(そことしてDOMにロード怠惰です、私の場合のように、間違いなくその方法でスピードテストを行うことに興味があるだろうCANこの方法は、怠惰な負荷に大きな遅延を追加した場合、結果の何千も)好奇心旺盛。
2015年

5
申し訳ありませんが、あなたの主張はいずれも真実ではありません。1. RegExpを絶対に使用できます。HTML値の内部を検索するのではなく、要素のテキスト値を検索する必要があります。2. mark.jsに実装されているように、発音区別符号文字でRegExpを絶対に使用できます。3. HTML表記はブラウザDOMの実際の文字に変換されるので、それらも絶対に使用します。
2016年

1
@julmot; へ1:これは、すべての要素を反復処理する必要があることを意味します。これがまさに私が行うことです。形式を失うことを気にしない限り、document.body.innerTextで検索することはできますが、非常に遅くなります。3. DOMではなく、text-elementのinnerTextまたはtextContentプロパティ内。つまり、テキスト要素を反復処理する必要があります。regEx AFAIKでは実行できません。2:mark.jsはわかりませんが、jQuery.eachを実行するすべてのことは避けます。
Stefan Steiger

1
@StefanSteiger 1.次に、RegExpを使用して検索することはまったくできないと書かれているため、決定関係を修正する必要があります。これは正しくありません。2. jQuery.eachを使用しません。何があなたをそう思わせたのですか?3.これは、少なくともFirefoxでは当てはまりません。&auml;たとえば、を使用しinnerHTMLた場合でも、実際の文字に変換されます。
2016

1
こんにちは@StefanSteiger実は、私はあなたのソリューションを使用しています。これは完璧です。しかし、IIに2つのスパンがあり、1つのスパンに卒業証書MSBTEのようなデータがあり、2番目のスパンに2012年のデータがあるようなPがある場合、いくつかの問題があります。今ハイライトしたい文字列がDiploma MSBTE 2012の場合、この文字列全体が機能しないことを確認しました。一致するすべてのものが1つのスパンに存在する場合は機能しますが、テキストコンテンツがdiffタグにある場合は、それは動作しません。これについて何か教えてもらえますか?
ガネシュク2018年

40

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

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

  • あなたは何度も何度も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にあります(プロジェクト参照)。


4
テキストを強調表示するだけでは、jQueryを含める十分な理由にはなりません。
ロイ

10
@ロイ私はこれを心に留めました。朗報です。v6.0.0 以降、mark.js はjQueryの依存関係を放棄し、jQueryプラグインとしてオプションで使用できるようになりました。
2016年

例外:登録されたイベントハンドラーを取得できず、匿名関数を設定できなかったため、1つ目のポイントは不可能です。2つ目:mark.jsは、2つのタグの間のテキストも検索しません。例: <span> s </ span> edはsedを検出しません... 3番目:まだテストしていないブラウザ(新しいバージョンを含む)が表示されるたびに、ブラウザが壊れる可能性があります。あなたがいくつのテストを書いても、それは常に真実です。17kbでは、マークはそれが行うには大きすぎます。
Stefan Steiger 2018年

@StefanSteigerとは何のことですか?その情報なしでは最初のポイントに何かを言うことはできません。ただし、2番目のコメントは間違っています。mark.jsはacrossElementsオプションを使用して、タグ間の一致を見つけることができます。そして3番目のコメントへ。mark.jsは、それが提供する機能と比較して大きくありません。そして、いいえ、将来的に何かが壊れる可能性はありません。mark.jsがテストされているためです。たとえば、Chrome 30の起動や、クロスブラウザユニットテストを備えたすべての新しいバージョンでテストされ、今後のバージョンで問題が発生することはありません。

@dude:最初の段落の後の3つのポイント。ああ、わかりました、私が見たデモでそのオプションがありません。その場合、それはいくつかの意味があります。しかし、それでも、私はそれが大きすぎると思います。
Stefan Steiger 2018年

10
function stylizeHighlightedString() {

    var text = window.getSelection();

    // For diagnostics
    var start = text.anchorOffset;
    var end = text.focusOffset - text.anchorOffset;

    range = window.getSelection().getRangeAt(0);

    var selectionContents = range.extractContents();
    var span = document.createElement("span");

    span.appendChild(selectionContents);

    span.style.backgroundColor = "yellow";
    span.style.color = "black";

    range.insertNode(span);
}

3
Mohit、SOへようこそ。コードのいくつかの説明がいいでしょう!
Nippey

別のノードを作成せずにテキストを選択する方法はありませんか?
Dave Gregory

@ user191433問題はテキストを選択することだけではなく、スタイルを適用することでもあります。そのためにはノードが必要です。
クリストフ

JavaScript span.style.backgroundColor = "yellow";がCSSに変換されることに注意/ヒントstyle="background-color: yellow;"-キャメルケースと破線表記の微妙な違いが、最初は私をつまずきました。
MarkHu 2013

1
stackoverflow.com/questions/7991474/…でのPS Mohitの回答は、このコードのより合理化されたバリアントです。(たとえば、ここでは単に診断/機能しない開始変数と終了変数を省略しています。)
MarkHu

7

これが私の正規表現の純粋なJavaScriptソリューションです:

function highlight(text) {
    document.body.innerHTML = document.body.innerHTML.replace(
        new RegExp(text + '(?!([^<]+)?<)', 'gi'),
        '<b style="background-color:#ff0;font-size:100%">$&</b>'
    );
}

これは、私が強調表示しようとしているテキストのブロックにHTMLタグが含まれている場合に完全に機能します。
John Chapman、

あなたはまた、例えば、正規表現パイプ記号を介して複数の単語を受け入れるように機能を微調整することができますone|two|three
KlemenTušar

テキストの最後に文字がある場合、テキストは置き換えられません>。動作するように使用する正規表現を変更し(?!([^<]+)?<)ます。
Archie Reyes

要求通りに変更されました。
KlemenTušar16年

パーフェクト!これは私にとって最高です
マルコブロメート

5

私も同じ問題を抱えており、大量のテキストがxmlhttpリクエストを通じて届きます。このテキストはHTML形式です。すべての出来事を強調する必要があります。

str='<img src="brown fox.jpg" title="The brown fox" />'
    +'<p>some text containing fox.</p>'

問題は、タグ内のテキストを強調表示する必要がないことです。たとえば、キツネを強調する必要があります:

今、私はそれを次のように置き換えることができます:

var word="fox";
word="(\\b"+ 
    word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
        + "\\b)";
var r = new RegExp(word,"igm");
str.replace(r,"<span class='hl'>$1</span>")

あなたの質問に答えるには:正規表現オプションのgを省略でき、最初の出現のみが置き換えられますが、これはまだimg srcプロパティ内のものであり、イメージタグを破棄します。

<img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span 
class='hl'>fox</span> />

これは私がそれを解決した方法ですが、正規表現で見逃した、より良い方法があるかどうか疑問に思っていました:

str='<img src="brown fox.jpg" title="The brown fox" />'
    +'<p>some text containing fox.</p>'
var word="fox";
word="(\\b"+ 
    word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
    + "\\b)";
var r = new RegExp(word,"igm");
str.replace(/(>[^<]+<)/igm,function(a){
    return a.replace(r,"<span class='hl'>$1</span>");
});

これは、<img src="word">またはをいじることなく機能する唯一の正規表現ソリューションでした<a href="word">
yvesmancera 2015年

1
黄金律:絶対に。使用する。レギュラー。式。に。混乱 約。と。XML。
ScottMcGready 2017

5

他のソリューションはどれも私のニーズに実際には適合していません。StefanSteigerのソリューションは期待どおりに機能しましたが、少し冗長すぎると感じました。

以下は私の試みです:

/**
 * Highlight keywords inside a DOM element
 * @param {string} elem Element to search for keywords in
 * @param {string[]} keywords Keywords to highlight
 * @param {boolean} caseSensitive Differenciate between capital and lowercase letters
 * @param {string} cls Class to apply to the highlighted keyword
 */
function highlight(elem, keywords, caseSensitive = false, cls = 'highlight') {
  const flags = caseSensitive ? 'gi' : 'g';
  // Sort longer matches first to avoid
  // highlighting keywords within keywords.
  keywords.sort((a, b) => b.length - a.length);
  Array.from(elem.childNodes).forEach(child => {
    const keywordRegex = RegExp(keywords.join('|'), flags);
    if (child.nodeType !== 3) { // not a text node
      highlight(child, keywords, caseSensitive, cls);
    } else if (keywordRegex.test(child.textContent)) {
      const frag = document.createDocumentFragment();
      let lastIdx = 0;
      child.textContent.replace(keywordRegex, (match, idx) => {
        const part = document.createTextNode(child.textContent.slice(lastIdx, idx));
        const highlighted = document.createElement('span');
        highlighted.textContent = match;
        highlighted.classList.add(cls);
        frag.appendChild(part);
        frag.appendChild(highlighted);
        lastIdx = idx + match.length;
      });
      const end = document.createTextNode(child.textContent.slice(lastIdx));
      frag.appendChild(end);
      child.parentNode.replaceChild(frag, child);
    }
  });
}

// Highlight all keywords found in the page
highlight(document.body, ['lorem', 'amet', 'autem']);
.highlight {
  background: lightpink;
}
<p>Hello world lorem ipsum dolor sit amet, consectetur adipisicing elit. Est vel accusantium totam, ipsum delectus et dignissimos mollitia!</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam, corporis.
  <small>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium autem voluptas perferendis dolores ducimus velit error voluptatem, qui rerum modi?</small>
</p>

正規表現でエスケープする必要がある特殊文字をキーワードに含めることができる場合は、escape-string-regexpのようなものを使用することもお勧めします。

const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);

これは私のためによく働いたが、それはまた、「「マーク解除」への道を必要とする
jwzumwalt

4

単純なTypeScriptの例

注:私は多くの点で@Stefanに同意しますが、単純な一致の強調表示だけが必要でした:

module myApp.Search {
    'use strict';

    export class Utils {
        private static regexFlags = 'gi';
        private static wrapper = 'mark';

        private static wrap(match: string): string {
            return '<' + Utils.wrapper + '>' + match + '</' + Utils.wrapper + '>';
        }

        static highlightSearchTerm(term: string, searchResult: string): string {
            let regex = new RegExp(term, Utils.regexFlags);

            return searchResult.replace(regex, match => Utils.wrap(match));
        }
    }
}

そして実際の結果を構築します:

module myApp.Search {
    'use strict';

    export class SearchResult {
        id: string;
        title: string;

        constructor(result, term?: string) {
            this.id = result.id;
            this.title = term ? Utils.highlightSearchTerm(term, result.title) : result.title;
        }
    }
}

3

HTML5以降、<mark></mark>タグを使用してテキストを強調表示できます。JavaScriptを使用して、これらのタグの間にテキスト/キーワードをラップすることができます。テキストをマークしたりマークを外したりする方法の小さな例を次に示します。

JSFIDDLEデモ


innerHTML危険です。イベントを削除します。

2
たとえば、JSFIDDLE "Lorem"を入力すると、最初のインスタンスのみがマークされるため、これも正しく機能しません。
agm1984

1
キーワードのすべての出現箇所を置き換える必要があるだけです。ここにグローバルに正規表現を持つ例jsfiddle.net/de5q704L/73
kasper Taeymans

2

2019年に早送りされ、Web APIはテキストの強調表示をネイティブでサポートするようになりました。

const selection = document.getSelection();
selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);

そして、あなたは行ってもいいです!anchorNodeは選択開始ノード、focusNodeは選択終了ノードです。そして、それらがテキストノードの場合、はoffsetそれぞれのノードの開始文字と終了文字のインデックスです。ここにドキュメントがあります

彼らはライブデモさえ持っています


ああ、これは素晴らしいです。次のように使用するだけです。selection.setBaseAndExtent(desiredNode、0、desiredNode、1); 必要な唯一のノードを強調表示します。グーテンベルクで動作します
tonyAndr

1

私もこの投稿で私が学んだことを試すことができると思っていました。

私が使用した:

function highlightSelection() {
			var userSelection = window.getSelection();
			for(var i = 0; i < userSelection.rangeCount; i++) {
				highlightRange(userSelection.getRangeAt(i));
			}
			
		}
			
			function highlightRange(range) {
			    var newNode = document.createElement("span");
			    newNode.setAttribute(
			       "style",
			       "background-color: yellow; display: inline;"
			    );
			    range.surroundContents(newNode);
			}
<html>
	<body contextmenu="mymenu">

		<menu type="context" id="mymenu">
			<menuitem label="Highlight Yellow" onclick="highlightSelection()" icon="/images/comment_icon.gif"></menuitem>
		</menu>
		<p>this is text, select and right click to high light me! if you can`t see the option, please use this<button onclick="highlightSelection()">button </button><p>

ここで試すこともできます:http : //henriquedonati.com/projects/Extension/extension.html

xc


0

ページの読み込み時にそれを強調表示したい場合は、新しい方法があります。

追加するだけ #:~:text=Highlight%20These

このリンクにアクセスしてみてください

/programming/38588721#:~:text=Highlight%20a%20text


-1

Range型でSurroundContents ()メソッドを使用します。その唯一の引数は、その範囲をラップする要素です。

function styleSelected() {
  bg = document.createElement("span");
  bg.style.backgroundColor = "yellow";
  window.getSelection().getRangeAt(0).surroundContents(bg);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.