<div class="title">
I am text node
<a class="edit">Edit</a>
</div>
Ich möchte den "Ich bin Textknoten" erhalten, möchte das "Bearbeiten" -Tag nicht entfernen und benötige eine browserübergreifende Lösung.
javascript
jquery
Val
quelle
quelle
Antworten:
Dadurch wird das
contents
ausgewählte Element abgerufen und eine Filterfunktion darauf angewendet. Die Filterfunktion gibt nur Textknoten zurück (dh die Knoten mitnodeType == Node.TEXT_NODE
).quelle
text()
weil diefilter
Funktion die Knoten selbst zurückgibt, nicht den Inhalt der Knoten.jQuery("*").each(function() { console.log(this.nodeType); })
und 1 für alle Knotentypen erhalten.Sie können den nodeValue des ersten childNode mit abrufen
http://jsfiddle.net/TU4FB/
quelle
null
einen Rückgabewert.Wenn Sie den Wert des ersten Textknotens im Element abrufen möchten, funktioniert dieser Code:
Sie können dies hier in Aktion sehen: http://jsfiddle.net/ZkjZJ/
quelle
curNode.nodeType == 3
stattdessennodeName
auch verwenden.curNode.nodeType == Node.TEXT_NODE
(numerischer Vergleich ist schneller, aber curNode.nodeType == 3 ist nicht lesbar - welcher Knoten hat Nummer 3?)curNode.NodeType === Node.TEXT_NODE
. Dieser Vergleich findet innerhalb einer Schleife unbekannter möglicher Iterationen statt. Der Vergleich zweier kleiner Zahlen ist besser als der Vergleich von Zeichenfolgen unterschiedlicher Länge (zeitliche und räumliche Überlegungen). Die richtige Frage in dieser Situation lautet "Welche Art / Art von Knoten habe ich?" Und nicht "Welchen Namen habe ich?". developer.mozilla.org/en-US/docs/Web/API/Node/nodeTypechildNodes
wissen, dass ein Elementknoten mehr als einen Textknoten haben kann . In einer generischen Lösung muss möglicherweise angegeben werden, auf welche Instanz eines Textknotens innerhalb eines Elementknotens Sie abzielen möchten (die erste, zweite, dritte usw.).Eine andere native JS-Lösung, die für "komplexe" oder tief verschachtelte Elemente nützlich sein kann, ist die Verwendung von NodeIterator .
NodeFilter.SHOW_TEXT
Geben Sie als zweites Argument ("whatToShow") an und iterieren Sie nur über die untergeordneten Textknoten des Elements.Sie können auch verwenden
TreeWalker
. Der Unterschied zwischen beiden besteht darin, dassNodeIterator
es sich um einen einfachen linearen Iterator handelt,TreeWalker
mit dem Sie auch über Geschwister und Vorfahren navigieren können.quelle
Reines JavaScript: Minimalistisch
Denken Sie immer zuerst daran, wenn Sie im DOM nach Text suchen.
MDN - Leerzeichen im DOM
In diesem Problem werden Sie auf die Struktur Ihres XML / HTML achten.
In diesem reinen JavaScript-Beispiel berücksichtige ich die Möglichkeit mehrerer Textknoten , die mit anderen Arten von Knoten verschachtelt werden könnten . Zunächst beurteile ich Leerzeichen jedoch nicht und überlasse diese Filteraufgabe einem anderen Code.
In dieser Version übergebe ich ein
NodeList
In aus dem aufrufenden / Client-Code.Wenn Sie
node.hasChildNodes()
zuerst testen , müssen Sie natürlich keine Vortestschleife verwendenfor
.Reines JavaScript: Robust
Hier verwendet die Funktion
getTextById()
zwei Hilfsfunktionen:getStringsFromChildren()
undfilterWhitespaceLines()
.getStringsFromChildren ()
filterWhitespaceLines ()
getTextById ()
Als nächstes wird der Rückgabewert (Array oder null) an den Clientcode gesendet, wo er behandelt werden soll. Hoffentlich sollte das Array Zeichenfolgenelemente aus echtem Text enthalten, keine Leerzeichen.
Leere Zeichenfolgen (
""
) werden nicht zurückgegeben, da Sie einen Textknoten benötigen, um das Vorhandensein von gültigem Text ordnungsgemäß anzuzeigen. Die Rückgabe (""
) kann den falschen Eindruck erwecken, dass ein Textknoten vorhanden ist, was dazu führt, dass jemand annimmt, dass er den Text durch Ändern des Werts von ändern kann.nodeValue
. Dies ist falsch, da bei einer leeren Zeichenfolge kein Textknoten vorhanden ist.Beispiel 1 :
Beispiel 2 :
Das Problem tritt auf, wenn Sie Ihren HTML-Code durch Ablesen leicht lesbar machen möchten. Obwohl es keinen von Menschen lesbaren gültigen Text gibt
"\n"
, gibt es immer noch Textknoten mit newline ( ) -Zeichen in ihren.nodeValue
Eigenschaften.Die Menschen sehen die Beispiele eins und zwei als funktional äquivalent - leere Elemente, die darauf warten, gefüllt zu werden. Das DOM unterscheidet sich vom menschlichen Denken. Aus diesem Grund
getStringsFromChildren()
muss die Funktion feststellen, ob Textknoten vorhanden sind, und die.nodeValue
Werte in einem Array zusammenfassen.In Beispiel zwei sind zwei Textknoten vorhanden
getStringFromChildren()
, die.nodeValue
beide zurückgeben ("\n"
). VerwendetfilterWhitespaceLines()
jedoch einen regulären Ausdruck, um Zeilen mit reinen Leerzeichen herauszufiltern.Ist das Zurückgeben
null
von Zeichen anstelle von newline ("\n"
) eine Form des Lügens des Client- / Aufrufcodes ? In menschlicher Hinsicht nein. In DOM-Begriffen ja. Hier geht es jedoch darum , Text abzurufen und nicht zu bearbeiten. Es gibt keinen menschlichen Text, um zum aufrufenden Code zurückzukehren.Man kann nie wissen, wie viele Zeilenumbrüche in HTML von jemandem erscheinen könnten. Das Erstellen eines Zählers, der nach dem "zweiten" Zeilenumbruchzeichen sucht, ist unzuverlässig. Es könnte nicht existieren.
Später könnte das Problem der Bearbeitung von Text in einem leeren
<p></p>
Element mit zusätzlichen Leerzeichen (Beispiel 2) natürlich bedeuten, dass alle bis auf einen Textknoten zwischen den Tags eines Absatzes zerstört (möglicherweise übersprungen) werden, um sicherzustellen, dass das Element genau das enthält, was es ist soll anzeigen.Unabhängig davon, außer in Fällen, in denen Sie etwas Außergewöhnliches tun, müssen Sie ermitteln, welche
.nodeValue
Eigenschaft des Textknotens den wahren, von Menschen lesbaren Text enthält, den Sie bearbeiten möchten.filterWhitespaceLines
bringt uns auf halbem Weg dorthin.Zu diesem Zeitpunkt haben Sie möglicherweise eine Ausgabe, die folgendermaßen aussieht:
Es gibt keine Garantie dafür, dass diese beiden Zeichenfolgen im DOM nebeneinander liegen. Wenn Sie sie also miteinander verbinden, entsteht
.join()
möglicherweise eine unnatürliche Zusammensetzung. Stattdessen müssen Sie im aufrufenden Code auswählengetTextById()
, mit welcher Zeichenfolge Sie arbeiten möchten.Testen Sie die Ausgabe.
Man könnte
.trim()
innerhalb von hinzufügengetStringsFromChildren()
, um führende und nachfolgende Leerzeichen zu entfernen (oder eine Reihe von Leerzeichen in eine Zeichenfolge mit der Länge Null umzuwandeln (""
), aber wie können Sie a priori wissen, was jede Anwendung möglicherweise mit dem Text (Zeichenfolge) geschehen muss? Sobald es gefunden ist, tun Sie es nicht. Überlassen Sie dies einer bestimmten Implementierung und lassen SiegetStringsFromChildren()
es generisch sein.Es kann Zeiten geben, in denen diese Spezifität (die
target
und solche) nicht erforderlich ist. Das ist großartig. Verwenden Sie in diesen Fällen eine einfache Lösung. Ein verallgemeinerter Algorithmus ermöglicht es Ihnen jedoch, einfache und komplexe Situationen zu berücksichtigen.quelle
ES6-Version, die den ersten # Textknoteninhalt zurückgibt
quelle
.from()
, um eine flach kopierte Array-Instanz zu erstellen. (2) Die Verwendung von.find()
, um einen String-Vergleich mit durchzuführen.nodeName
. Verwendennode.NodeType === Node.TEXT_NODE
wäre besser. (3) Die Rückgabe einer leeren Zeichenfolge, wenn kein Wert vorhanden istnull
, ist wahrer, wenn kein Textknoten gefunden wird. Wenn kein Textknoten gefunden wird, muss möglicherweise einer erstellt werden! Wenn Sie eine leere Zeichenfolge zurückgeben,""
können Sie den falschen Eindruck erwecken, dass ein Textknoten vorhanden ist und normal bearbeitet werden kann. Im Wesentlichen ist die Rückgabe einer leeren Zeichenfolge eine Notlüge und wird am besten vermieden.[...node.childNodes]
, um HTMLCollection in Arrays zu konvertieren.text() - for jquery
quelle
a
Elements erhalten: jsfiddle.net/ekHJH.
am Anfang Ihres Selektors, was bedeutet, dass Sie tatsächlich den Text destitle
Elements erhalten, nicht Elemente mitclass="title"
.innerText
ist eine alte IE-Konvention, die erst kürzlich übernommen wurde. In Bezug auf Standard-DOM-Skriptenode.nodeValue
erfasst man den Text eines Textknotens.Dadurch wird auch das Leerzeichen ignoriert, sodass Sie nie den leeren TextNodes..code mit Javascript erhalten haben.
Überprüfen Sie es auf jsfiddle: - http://jsfiddle.net/webx/ZhLep/
quelle
curNode.nodeType === Node.TEXT_NODE
wäre besser. Die Verwendung eines Zeichenfolgenvergleichs und eines regulären Ausdrucks innerhalb einer Schleife ist eine Lösung mit geringer Leistung, insbesondere wenn die GrößeoDiv.childNodes.length
zunimmt. Dieser Algorithmus löst die spezifische Frage des OP, jedoch möglicherweise mit schrecklichen Leistungskosten. Wenn sich die Anordnung oder Anzahl der Textknoten ändert, kann nicht garantiert werden, dass diese Lösung eine genaue Ausgabe zurückgibt. Mit anderen Worten, Sie können nicht genau auf den gewünschten Textknoten abzielen. Sie sind der HTML-Struktur und der Anordnung der Texte dort ausgeliefert.Sie können auch den XPath-
text()
Knotentest verwenden, um nur die Textknoten abzurufen. Beispielsweisequelle
Dies ist meine Lösung in ES6, um eine Zeichenfolge zu erstellen, die dem verketteten Text aller untergeordneten Knoten widerspricht (rekursiv) . Beachten Sie, dass Sie auch die shdowroot von Kinderknoten besuchen.
Diese Lösung wurde von der Lösung von https://stackoverflow.com/a/41051238./1300775 inspiriert .
quelle