Javascript Regex zum Ersetzen von Text NICHT in HTML-Attributen [duplicate]

Lesezeit: 5 Minuten

Ich möchte, dass ein Javascript Regex eine bestimmte Liste von Wörtern in einen bestimmten Anfang (<span>) und End-Tag (dh </span>), aber nur, wenn das Wort tatsächlich „sichtbarer Text“ auf der Seite ist und nicht innerhalb eines HTML-Attributs (z. B. im Titel-Tag eines Links oder innerhalb einer <script></script> Block.

Ich habe eine JS Fiddle mit dem grundlegenden Setup erstellt: http://jsfiddle.net/4YCR6/1/

  • Wie die anderen sagten, ist es normalerweise nicht die beste Idee, HTML mit einer Regex zu handhaben. Aber es gibt Fälle, in denen es einfach der einfachste Weg ist. Versuche dies: jsfiddle aktualisiert Auf rubulär

    – morja

    5. Mai 11 um 22:58 Uhr


  • Siehe stackoverflow.com/questions/3241169/…

    – Ryan

    4. März 13 um 22:38 Uhr

Javascript Regex zum Ersetzen von Text NICHT in HTML Attributen duplicate
TJ Crowder

HTML ist zu komplex, um es zuverlässig mit einem regulären Ausdruck zu analysieren.

Wenn Sie dies clientseitig tun möchten, können Sie ein Dokumentfragment und/oder einen getrennten DOM-Knoten erstellen (von denen keiner irgendwo angezeigt wird) und ihn mit Ihrer HTML-Zeichenfolge initialisieren, dann den resultierenden DOM-Baum durchlaufen und verarbeiten Textknoten. (Oder verwenden Sie eine Bibliothek, um Ihnen dabei zu helfen, obwohl es eigentlich ganz einfach ist.)

Hier ist ein DOM-Walking-Beispiel. Dieses Beispiel ist leicht einfacher als Ihr Problem, weil es nur den Text aktualisiert, der Struktur keine neuen Elemente hinzufügt (Teile des Textes in spans beinhaltet die Aktualisierung der Struktur), aber es sollte Sie in Gang bringen. Hinweise, was Sie am Ende ändern müssen.

var html =
    "<p>This is a test.</p>" +
    "<form><input type="text" value="test value"></form>" +
    "<p class="testing test">Testing here too</p>";
var frag = document.createDocumentFragment();
var body = document.createElement('body');
var node, next;

// Turn the HTML string into a DOM tree
body.innerHTML = html;

// Walk the dom looking for the given text in text nodes
walk(body);

// Insert the result into the current document via a fragment
node = body.firstChild;
while (node) {
  next = node.nextSibling;
  frag.appendChild(node);
  node = next;
}
document.body.appendChild(frag);

// Our walker function
function walk(node) {
  var child, next;

  switch (node.nodeType) {
    case 1:  // Element
    case 9:  // Document
    case 11: // Document fragment
      child = node.firstChild;
      while (child) {
        next = child.nextSibling;
        walk(child);
        child = next;
      }
      break;
    case 3: // Text node
      handleText(node);
      break;
  }
}

function handleText(textNode) {
  textNode.nodeValue = textNode.nodeValue.replace(/test/gi, "TEST");
}

Live-Beispiel

Die Änderungen, die Sie vornehmen müssen, sind in handleText. Genauer gesagt, anstatt zu aktualisieren nodeValuemüssen Sie:

  • Finden Sie den Index des Anfangs jedes Wortes innerhalb der nodeValue Schnur.
  • Benutzen Node#splitText um den Textknoten in bis zu drei Textknoten zu teilen (der Teil vor Ihrem übereinstimmenden Text, der Teil, der ist Ihren passenden Text und den Teil, der auf Ihren passenden Text folgt).
  • Benutzen document.createElement um das Neue zu erschaffen span (Das ist buchstäblich gerecht span = document.createElement('span')).
  • Benutzen Node#insertBefore das neue einzufügen span vor dem dritten Textknoten (der den Text enthält, der Ihrem übereinstimmenden Text folgt); Es ist in Ordnung, wenn Sie keinen dritten Knoten erstellen mussten, weil sich Ihr übereinstimmender Text am Ende des Textknotens befand. Passen Sie ihn einfach an null als die refChild.
  • Benutzen Node#appendChild um den zweiten Textknoten (den mit dem passenden Text) in die zu verschieben span. (Es ist nicht erforderlich, es zuerst von seinem übergeordneten Element zu entfernen; appendChild macht das für dich.)

  • Fun Fact: Fast fünf Jahre später verwendeten sie diesen Code in die Drumpfinator Chrome-Erweiterung angeschlossen Letzte Woche heute Abend mit JohnOliver. Urkomisch!

    – TJ Crowder

    1. März 16 um 13:49 Uhr

  • Das hast du auch herausgefunden? Oh warte, es ist deine Antwort? wurdest du konsultiert oder hast du wie ich in der erweiterung geschaut?

    – Klammer110

    1. März 16 um 15:35 Uhr

  • @brace110: Eine sehr nette junge Frau, die sich den Quellcode angesehen hat, hat mir eine E-Mail geschrieben. 🙂

    – TJ Crowder

    1. März 16 um 15:40 Uhr

  • Benutze es selbst für etwas Ähnliches, natürlich mit korrekter Zuordnung 🙂

    – Stephen Tetreault

    8. Dezember 16 um 17:36 Uhr

Javascript Regex zum Ersetzen von Text NICHT in HTML Attributen duplicate
Tim unten

Die Antwort von TJ Crowder ist richtig. Codetechnisch bin ich noch etwas weiter gegangen: Hier ist ein fertiges Beispiel, das in allen gängigen Browsern funktioniert. Ich habe bereits Variationen dieses Codes auf Stack Overflow gepostet (zum Beispiel hier und hier) und ihn nett und generisch gestaltet, damit ich (oder jemand anderes) ihn nicht viel ändern muss, um ihn wiederzuverwenden.

jsFiddle-Beispiel: http://jsfiddle.net/7Vf5J/38/

Code:

// Reusable generic function
function surroundInElement(el, regex, surrounderCreateFunc) {
    // script and style elements are left alone
    if (!/^(script|style)$/.test(el.tagName)) {
        var child = el.lastChild;
        while (child) {
            if (child.nodeType == 1) {
                surroundInElement(child, regex, surrounderCreateFunc);
            } else if (child.nodeType == 3) {
                surroundMatchingText(child, regex, surrounderCreateFunc);
            }
            child = child.previousSibling;
        }
    }
}

// Reusable generic function
function surroundMatchingText(textNode, regex, surrounderCreateFunc) {
    var parent = textNode.parentNode;
    var result, surroundingNode, matchedTextNode, matchLength, matchedText;
    while ( textNode && (result = regex.exec(textNode.data)) ) {
        matchedTextNode = textNode.splitText(result.index);
        matchedText = result[0];
        matchLength = matchedText.length;
        textNode = (matchedTextNode.length > matchLength) ?
            matchedTextNode.splitText(matchLength) : null;
        // Ensure searching starts at the beginning of the text node
        regex.lastIndex = 0;
        surroundingNode = surrounderCreateFunc(matchedTextNode.cloneNode(true));
        parent.insertBefore(surroundingNode, matchedTextNode);
        parent.removeChild(matchedTextNode);
    }
}

// This function does the surrounding for every matched piece of text
// and can be customized  to do what you like
function createSpan(matchedTextNode) {
    var el = document.createElement("span");
    el.style.color = "red";
    el.appendChild(matchedTextNode);
    return el;
}

// The main function
function wrapWords(container, words) {
    // Replace the words one at a time to ensure "test2" gets matched
    for (var i = 0, len = words.length; i < len; ++i) {
        surroundInElement(container, new RegExp(words[i]), createSpan);
    }
}

wrapWords(document.getElementById("container"), ["test2", "test"]);

  • Das ist genau das, wonach ich gesucht habe. Wie könnte ich diesen Fall jedoch vollständig ignorieren?

    – Mike Mellor

    5. Juni 14 um 15:08 Uhr

  • @MikeMellor: Ändern new RegExp(words[i], "g") zu new RegExp(words[i], "gi").

    – Tim unten

    5. Juni 14 um 15:20 Uhr

  • Gott, das war einfach, ich sollte wirklich etwas über reguläre Ausdrücke lernen. Danke Tim

    – Mike Mellor

    5. Juni 14 um 15:22 Uhr


  • @MikeMellor: Jeder sollte reguläre Ausdrücke lernen 🙂

    – Tim unten

    5. Juni 14 um 16:41 Uhr

  • @TimDown: Danke für den Code. Es muss jedoch beachtet werden, dass es einen Fehler hat: Es überspringt einige Spiele. Etwas reparieren, regex.lastIndex = 0; muss nach dem hinzugefügt werden textNode = ... Zeile in SurroundMatchingText.

    – Dmitrych

    13. Juli 15 um 2:31 Uhr

.

822150cookie-checkJavascript Regex zum Ersetzen von Text NICHT in HTML-Attributen [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy