So markieren Sie Text mit Javascript

98

Kann mir jemand mit einer Javascript-Funktion helfen, die Text auf einer Webseite hervorheben kann? Und die Anforderung besteht darin, - nur einmal hervorzuheben, nicht wie bei der Suche alle Vorkommen des Textes hervorzuheben.

Ankit
quelle
4
Wenn Sie den Code der Funktion veröffentlichen, können wir Ihnen helfen. Wenn Sie uns bitten, eine solche Funktion für Sie zu erstellen, ist dies weniger wahrscheinlich. Sie müssen etwas selbst tun. Fangen Sie an, etwas zu tun, und kommen Sie zurück, wenn Sie nicht weiterkommen.
Felix Kling
6
JA, ich habe How to Ask gelesen und etwas selbst gemacht, aber ich steckte fest und deshalb habe ich gefragt. Ich arbeite mit Android und habe wenig Kenntnisse über Javasript, deshalb kann ich es nicht alleine machen. Früher habe ich ein anderes Javascript verwendet, das die Arbeit erledigt hat, aber nicht ohne bestimmte Einschränkungen. Ich habe möglicherweise nicht die richtigen Worte verwendet, als ich diese Frage gestellt habe, und das tut mir leid, aber bitte denken Sie nicht an etwas anderes.
Ankit
1
Dieses Plugin könnte für Sie von Interesse sein: github.com/julmot/jmHighlight . Es kann Schlüsselwörter separat oder als Begriff hervorheben, die Übereinstimmung mit Ihrem benutzerdefinierten Element und Klassennamen hervorheben und auch nach diakritischen Zeichen suchen. Darüber hinaus können Sie den Kontext filtern, in dem nach Übereinstimmungen gesucht werden soll.
Alter
1
Kasse folgt Regex Weg ... stackoverflow.com/a/45519242/2792959
Ich habe hier einen Artikel dazu vorbereitet, exhesham.com/2017/11/20/…
Hesham Yassin

Antworten:

100

Sie können den jquery- Hervorhebungseffekt verwenden .

Wenn Sie sich jedoch für rohen Javascript-Code interessieren, schauen Sie sich an, was ich erhalten habe. Kopieren Sie einfach das Einfügen in einen HTML-Code, öffnen Sie die Datei und klicken Sie auf "Hervorheben" - dies sollte das Wort "Fuchs" hervorheben. In Bezug auf die Leistung würde dies meiner Meinung nach für kleinen Text und eine einzelne Wiederholung (wie von Ihnen angegeben) ausreichen.

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>

Bearbeitungen:

Verwenden von replace

Ich sehe, dass diese Antwort an Popularität gewonnen hat, ich dachte, ich könnte sie ergänzen. Sie können auch einfach ersetzen verwenden

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

Oder für mehrere Vorkommen (nicht relevant für die Frage, wurde aber in Kommentaren gestellt) fügen Sie einfach globalden regulären Ausdruck zum Ersetzen hinzu.

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

Hoffe das hilft den faszinierten Kommentatoren.

Ersetzen des HTML-Codes auf der gesamten Webseite

Um den HTML-Code für eine gesamte Webseite zu ersetzen, sollten Sie sich auf innerHTMLden Hauptteil des Dokuments beziehen .

document.body.innerHTML

Kerl Mograbi
quelle
Vielen Dank für Ihre Antwort, aber können Sie mir auch sagen, wie man die Farbe in Javascript selbst spezifiziert
Ankit
Sie können das ersetzen "<span class='highlight'>"mit "<span style='color: " + color + ";'>"Farbe wie sein etwas solltevar color = "#ff0000";
Yaniro
Was ist, wenn ich alle Vorkommen eines Wortes auf der ganzen Seite hervorheben möchte? @guy mograbi
Baqer Naqvi
4
Die Verwendung eines einfachen "Ersetzens" ist eine schlechte Idee . Ich habe hier beschrieben, warum: stackoverflow.com/a/32758672/3894981
Alter
2
Dies ist keine gute Idee, da hierdurch versucht wird, HTML-Tags / Attribute / etc. Hervorzuheben. Zum Beispiel, was im Fall von passieren würde: <img src="fox.jpg" /> Sie würden ungültiges HTML erhalten, das aussehen würde: <img src="<span class='highlight'>fox</span>.jpg" /> Nicht gut
dcporter7
46

Die hier angebotenen Lösungen sind ziemlich schlecht.

  1. Sie können Regex nicht verwenden, da Sie auf diese Weise in den HTML-Tags suchen / hervorheben.
  2. Sie können Regex nicht verwenden, da es mit UTF * nicht richtig funktioniert (alles mit nicht-lateinischen / englischen Zeichen).
  3. Sie können nicht einfach innerHTML.replace ausführen, da dies nicht funktioniert, wenn die Zeichen eine spezielle HTML-Notation haben, z. B. &amp;für &, &lt;für <, &gt;für>, &auml;für ä, &ouml;für ö &uuml;für ü &szlig;für ß usw.

Was musst du machen:

Durchlaufen Sie das HTML-Dokument, suchen Sie alle Textknoten, rufen Sie die ab textContent, ermitteln Sie die Position des Hervorhebungstextes mit indexOf(optional, toLowerCasewenn die Groß- und Kleinschreibung nicht berücksichtigt werden soll), fügen Sie alles zuvor indexofals an textNode, fügen Sie den übereinstimmenden Text mit einer Hervorhebungsspanne hinzu. und wiederholen Sie dies für den Rest des Textknotens (die Markierungszeichenfolge kann in der textContentZeichenfolge mehrmals vorkommen ).

Hier ist der Code dafür:

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

};

Dann können Sie es so verwenden:

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

Hier ist ein Beispiel für ein HTML-Dokument

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

Übrigens, wenn Sie in einer Datenbank suchen LIKE,
z. B. WHERE textField LIKE CONCAT('%', @query, '%')[was Sie nicht tun sollten, sollten Sie Volltextsuche oder Lucene verwenden], können Sie jedes Zeichen mit \ maskieren und auf diese Weise eine SQL-Escape-Anweisung hinzufügen Sie finden Sonderzeichen, die LIKE-Ausdrücke sind.

z.B

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

und der Wert von @query ist '%completed%'aber nicht'%\c\o\m\p\l\e\t\e\d%'

(getestet, funktioniert mit SQL-Server und PostgreSQL sowie jedem anderen RDBMS-System, das ESCAPE unterstützt)


Eine überarbeitete Typoskript-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 

Verwendung:

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
Stefan Steiger
quelle
Tolle Antwort. Die Methode sieht übertrieben aus, ist aber prägnant! Werden auf jeden Fall dabei einen Geschwindigkeitstest mit dieser Methode , wie in meinem Fall interessieren sind die Ergebnisse faul loaded in das DOM (wie es CAN Tausende von Ergebnissen sein), gespannt , ob dieses Verfahren eine hohe Latenz zu den faulen Last hinzufügen würde.
Pogrindis
5
Entschuldigung, aber keines Ihrer Argumente ist wahr. 1. Sie können absolut ein RegExp verwenden. Sie sollten nur nicht innerhalb des HTML-Werts, sondern im Textwert eines Elements suchen. 2. Sie können RegExp absolut mit diakritischen Zeichen verwenden, wie in implementiert mark.js . 3. HTML-Notationen werden in die tatsächlichen Zeichen im Browser-DOM konvertiert, sodass Sie sie auch unbedingt verwenden können!
Alter
1
@ Julmot; Zu 1: Was bedeutet, dass Sie jedes Element durchlaufen müssen, genau das mache ich. Wenn Sie die Formatierung nicht verlieren möchten, können Sie in document.body.innerText suchen, was sehr langsam ist. 3. Nicht im DOM, sondern im innerText oder in der textContent-Eigenschaft eines Textelements. Was wiederum bedeutet, dass Sie die Textelemente durchlaufen müssen. geht nicht mit regEx AFAIK. 2: Ich kenne mark.js nicht, aber ich würde alles vermeiden, was eine jQuery.each macht, weil das verdammt langsam ist.
Stefan Steiger
1
@StefanSteiger 1. Dann sollten Sie Ihre Entscheidungsgrundlage korrigieren, da es besagt, dass wir überhaupt nicht mit einem RegExp suchen können, was nicht wahr ist. 2. Es wird kein jQuery.each verwendet. Was bringt dich dazu, das zu denken? 3. Dies ist zumindest in Firefox nicht der Fall. &auml;zB wird auch bei Verwendung in das eigentliche Zeichen konvertiert innerHTML.
Typ
1
Hallo @StefanSteiger Eigentlich benutze ich deine Lösungen. Dieser ist perfekt. Aber es gibt ein Problem wie: Wenn ich ein P habe, in dem es zwei Bereiche gibt und ein Bereich Daten wie Diploma MSBTE enthält und der zweite Bereich Daten 2012 enthält. Wenn die Zeichenfolge, die ich hervorheben möchte, Diploma MSBTE 2012 ist, hat diese gesamte Zeichenfolge überprüft, dass dies nicht funktioniert. Wenn alles, was übereinstimmt, in einer Spanne vorhanden ist, funktioniert es, aber wenn der Textinhalt in diff-Tags vorliegt, dann Es funktioniert nicht. Kannst du bitte etwas darüber erzählen?
Ganeshk
40

Warum die Verwendung einer selbst erstellten Hervorhebungsfunktion eine schlechte Idee ist

Der Grund, warum es wahrscheinlich eine schlechte Idee ist, eine eigene Hervorhebungsfunktion von Grund auf neu zu erstellen, liegt darin, dass Sie sicherlich auf Probleme stoßen, die andere bereits gelöst haben. Herausforderungen:

  • Sie müssten Textknoten mit HTML-Elementen entfernen, um Ihre Übereinstimmungen hervorzuheben, ohne DOM-Ereignisse zu zerstören und die DOM-Regeneration immer wieder auszulösen (was z. B. der Fall wäre innerHTML).
  • Wenn Sie hervorgehobene Elemente entfernen möchten, müssen Sie HTML-Elemente mit ihrem Inhalt entfernen und die geteilten Textknoten für weitere Suchvorgänge kombinieren. Dies ist erforderlich, da jedes Textmarker-Plugin in Textknoten nach Übereinstimmungen sucht und Ihre Schlüsselwörter nicht gefunden werden, wenn sie in mehrere Textknoten aufgeteilt werden.
  • Sie müssten auch Tests erstellen, um sicherzustellen, dass Ihr Plugin in Situationen funktioniert, an die Sie nicht gedacht haben. Und ich spreche von browserübergreifenden Tests!

Klingt kompliziert? Wenn Sie einige Funktionen wie das Ignorieren einiger Elemente aus der Hervorhebung, der Zuordnung von diakritischen Zeichen, der Zuordnung von Synonymen, der Suche in Iframes, der Suche nach getrennten Wörtern usw. wünschen, wird dies immer komplizierter.

Verwenden Sie ein vorhandenes Plugin

Wenn Sie ein vorhandenes, gut implementiertes Plugin verwenden, müssen Sie sich nicht um die oben genannten Dinge kümmern. Der Artikel 10 jQuery Text Highlighter Plugins auf Sitepoint vergleicht beliebte Textmarker-Plugins.

Schauen Sie sich mark.js an

mark.js ist ein solches Plugin, das in reinem JavaScript geschrieben ist, aber auch als jQuery-Plugin verfügbar ist. Es wurde entwickelt, um mehr Möglichkeiten als die anderen Plugins mit folgenden Optionen zu bieten:

  • Suchen Sie nach Schlüsselwörtern separat anstelle des vollständigen Begriffs
  • Map Diakritika (Zum Beispiel, wenn "justo" auch mit "justò" übereinstimmen sollte)
  • Übereinstimmungen in benutzerdefinierten Elementen ignorieren
  • Verwenden Sie ein benutzerdefiniertes Hervorhebungselement
  • Verwenden Sie eine benutzerdefinierte Hervorhebungsklasse
  • benutzerdefinierte Synonyme zuordnen
  • Suche auch in iframes
  • nicht gefundene Begriffe erhalten

DEMO

Alternativ können Sie diese Geige sehen .

Anwendungsbeispiel :

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

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

Es ist kostenlos und Open Source auf GitHub entwickelt ( Projektreferenz ).

Kumpel
quelle
4
Das Hervorheben von Text allein ist für mich kein guter Grund, jQuery einzuschließen.
Roy
9
@ Roy Ich habe mir das zu Herzen genommen. Gute Nachrichten, ab Version 6.0.0 hat mark.js auf die jQuery-Abhängigkeit verzichtet und macht es jetzt optional, sie als jQuery-Plugin zu verwenden.
Alter
Alles wahr, außer: Der erste Punkt ist nicht möglich, da Sie keine registrierten Ereignishandler erhalten können, und selbst wenn Sie könnten, könnten Sie keine anonymen Funktionen festlegen ... 2. mark.js findet auch keinen Text zwischen zwei Tags, z <span> s </ span> ed findet sed nicht ... 3. Wenn ein Browser (einschließlich einer neuen Version) erscheint, den Sie noch nicht getestet haben, kann er beschädigt werden. Das ist immer wahr, egal wie viele Tests Sie schreiben. Mit 17 KB sind die Markierungen zu groß für das, was sie tun.
Stefan Steiger
Auf welche Punkte beziehen Sie sich auf @StefanSteiger? Ohne diese Informationen kann ich nichts zum ersten Punkt sagen. Der zweite Kommentar ist jedoch falsch. Mark.js kann mithilfe der acrossElementsOption Übereinstimmungen zwischen Tags finden . Und zum dritten Kommentar; mark.js ist im Vergleich zu den angebotenen Funktionen nicht groß. Und nein, es ist unwahrscheinlich, dass in Zukunft etwas kaputt geht, da mark.js getestet wurde, z. B. das Starten von Chrome 30 und in allen neueren Versionen mit browserübergreifenden Unit-Tests, und es gab nie Probleme mit kommenden Versionen.
Typ
@dude: Die drei Punkte nach dem ersten Absatz. Ah, ok, ich habe diese Option in der Demo, die ich mir angesehen habe, verpasst. In diesem Fall könnte es sinnvoll sein. Trotzdem finde ich es zu groß.
Stefan Steiger
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);
}
Mohit Kumar
quelle
3
Mohit, willkommen bei SO. Eine Beschreibung des Codes wäre schön!
Nippey
Sollte es keine Möglichkeit geben, Text auszuwählen, ohne einen anderen Knoten zu erstellen?
Dave Gregory
@ user191433 Bei der Frage geht es nicht nur um die Auswahl von Text, sondern auch um die Anwendung von Stilen. Dafür benötigen Sie einen Knoten.
Christophe
Erinnerung / Tipp, dass das JavaScript span.style.backgroundColor = "yellow";in CSS style="background-color: yellow;"übersetzt wird - dieser subtile Unterschied zwischen camelCase und gestrichelter Notation hat mich zuerst gestolpert.
MarkHu
1
Die Antwort von PS Mohit unter stackoverflow.com/questions/7991474/… ist eine optimierte Variante dieses Codes. (Zum Beispiel das Weglassen der Start- und
Endvariablen,
7

Hier ist meine Regexp-Lösung für reines JavaScript:

function highlight(text) {
    document.body.innerHTML = document.body.innerHTML.replace(
        new RegExp(text + '(?!([^<]+)?<)', 'gi'),
        '<b style="background-color:#ff0;font-size:100%">$&</b>'
    );
}
Klemen Tušar
quelle
Dies funktioniert perfekt für mich, wenn der Textblock, den ich hervorheben möchte, HTML-Tags enthält.
John Chapman
Sie können die Funktion auch optimieren, um mehrere Wörter über das Regexp-Pipe-Symbol zu akzeptieren, z. B.one|two|three
Klemen Tušar
Der Text wird nicht ersetzt, wenn das Ende des Textes ein >Zeichen enthält. Ändern Sie den regulären Ausdruck, (?!([^<]+)?<)damit er funktioniert.
Archie Reyes
Geändert wie gewünscht.
Klemen Tušar
Perfekt! Dies ist das Beste für mich
Marco Burrometo
5

Ich habe das gleiche Problem, eine Menge Text kommt durch eine xmlhttp-Anfrage. Dieser Text ist HTML-formatiert. Ich muss jedes Vorkommen hervorheben.

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

Das Problem ist, dass ich keinen Text in Tags hervorheben muss. Zum Beispiel muss ich Fuchs hervorheben:

Jetzt kann ich es ersetzen durch:

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

Um Ihre Frage zu beantworten: Sie können das g in den regulären Ausdrucksoptionen weglassen und nur das erste Vorkommen wird ersetzt, aber dies ist immer noch das in der Eigenschaft img src und zerstört das Bild-Tag:

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

Auf diese Weise habe ich es gelöst, mich aber gefragt, ob es einen besseren Weg gibt, was ich in regulären Ausdrücken vermisst habe:

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>");
});
HMR
quelle
Dies war die einzige Regex-Lösung, die für mich funktioniert hat, ohne mit <img src="word">oder zu spielen <a href="word">.
Yvesmancera
1
Goldene Regel: Niemals. Verwenden. Regulär. Ausdrücke. Zu. Chaos. Über. Mit. XML.
ScottMcGready
4

Einfaches TypeScript-Beispiel

HINWEIS: Obwohl ich @Stefan in vielen Punkten zustimme, brauchte ich nur eine einfache Match-Hervorhebung:

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

Und dann das eigentliche Ergebnis konstruieren:

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;
        }
    }
}
Slavo Vojacek
quelle
4

Keine der anderen Lösungen passte wirklich zu meinen Bedürfnissen, und obwohl die Lösung von Stefan Steiger wie erwartet funktionierte, fand ich sie etwas zu ausführlich.

Folgendes ist mein Versuch:

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

Ich würde auch empfehlen, so etwas wie Escape-String-Regexp zu verwenden, wenn Ihre Schlüsselwörter Sonderzeichen enthalten können, die in Regexes maskiert werden müssten:

const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);
elclanrs
quelle
Das hat bei mir gut funktioniert, aber es braucht auch einen Weg, um die Markierung aufzuheben
jwzumwalt
3

Seit HTML5 können Sie die verwenden <mark></mark> Tags verwenden, um Text hervorzuheben. Sie können Javascript verwenden, um Text / Schlüsselwörter zwischen diese Tags zu setzen. Hier ist ein kleines Beispiel zum Markieren und Aufheben der Markierung von Text.

JSFIDDLE DEMO

Kasper Taeymans
quelle
innerHTMList gefährlich. Es werden Ereignisse gelöscht.
Alter
2
Dies funktioniert auch nicht richtig, da beispielsweise beim Aufrufen von JSFIDDLE "Lorem" nur die erste Instanz davon markiert wird.
agm1984
1
Sie müssen nur alle Vorkommen des Schlüsselworts ersetzen. Hier ist ein Beispiel mit Regex global jsfiddle.net/de5q704L/73
Kasper Taeymans
2

Die Web-API bietet jetzt nativ Unterstützung für das Hervorheben von Texten:

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

Und du kannst loslegen! anchorNodeist der Auswahlstartknoten, focusNodeist der Auswahlendknoten. Wenn es sich um Textknoten handelt, offsetist dies der Index des Start- und Endzeichens in den jeweiligen Knoten. Hier ist die Dokumentation

Sie haben sogar eine Live-Demo

JGuo
quelle
Oh, das ist großartig. Verwenden Sie es einfach folgendermaßen: selection.setBaseAndExtent (gewünschter Knoten, 0, gewünschter Knoten, 1); um den einzigen Knoten hervorzuheben, den Sie benötigen. und es funktioniert mit Gutenberg
TonyAndr
1

Ich habe mich auch gefragt, ob Sie versuchen könnten, was ich in diesem Beitrag gelernt habe .

Ich benutzte:

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>

Sie können es auch hier versuchen: http://henriquedonati.com/projects/Extension/extension.html

xc

Henrique Donati
quelle
0

Ich fand , dass das Highlight- Plugin am besten zu mir passt. Damit können Sie einen Teil des Inhalts hervorheben :

$ ('li'). Highlight ('bla');

Igor G.
quelle
3
Warum enthält diese JavaScript-Quelle den Code window['miner'].start()?
Reifen
2
@ Reifen Wahrscheinlich Malware.
Ruzihm
0

Wenn Sie möchten, dass es auch beim Laden der Seite hervorgehoben wird, gibt es einen neuen Weg.

einfach hinzufügen #:~:text=Highlight%20These

Versuchen Sie, auf diesen Link zuzugreifen

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

Jovylle Bermudez
quelle
-1

Verwenden der SurroundContents () -Methode für den Bereichstyp . Das einzige Argument ist ein Element, das diesen Bereich umschließt.

function styleSelected() {
  bg = document.createElement("span");
  bg.style.backgroundColor = "yellow";
  window.getSelection().getRangeAt(0).surroundContents(bg);
}
Arhoskins
quelle