Ich möchte alle absteigenden Textknoten eines Elements als jQuery-Sammlung erhalten. Was ist der beste Weg, das zu tun?
Antworten
Zu viele Anzeigen?JQuery verfügt nicht über eine praktische Funktion für diese Aufgabe. Sie müssen Folgendes kombinieren contents()
, die nur untergeordnete Knoten, aber auch Textknoten enthält, mit find()
, die alle nachgeordneten Elemente, aber keine Textknoten enthält. Hier ist, was ich habe mit kommen:
var getTextNodesIn = function(el) {
return $(el).find(":not(iframe)").addBack().contents().filter(function() {
return this.nodeType == 3;
});
};
getTextNodesIn(el);
Hinweis: Wenn Sie jQuery 1.7 oder früher verwenden, wird der obige Code nicht funktionieren. Um dies zu beheben, ersetzen Sie addBack()
con andSelf()
. andSelf()
ist veraltet zu Gunsten von addBack()
ab 1.8.
Dies ist im Vergleich zu reinen DOM-Methoden etwas ineffizient und muss eine hässliche Umgehung für jQuery's Überladung der contents()
Funktion (Dank an @rabidsnail in den Kommentaren für den Hinweis, dass aus), so ist hier nicht jQuery Lösung mit einer einfachen rekursiven Funktion. Die includeWhitespaceNodes
steuert, ob Textknoten mit Leerzeichen in der Ausgabe enthalten sind oder nicht (in jQuery werden sie automatisch herausgefiltert).
Aktualisieren: Fehler behoben, wenn includeWhitespaceNodes fehlerhaft ist.
function getTextNodesIn(node, includeWhitespaceNodes) {
var textNodes = [], nonWhitespaceMatcher = /\S/;
function getTextNodes(node) {
if (node.nodeType == 3) {
if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
textNodes.push(node);
}
} else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
getTextNodes(node.childNodes[i]);
}
}
}
getTextNodes(node);
return textNodes;
}
getTextNodesIn(el);
jQuery.contents()
kann verwendet werden mit jQuery.filter
um alle untergeordneten Textknoten zu finden. Mit einem kleinen Trick können Sie auch Textknoten von Enkeln finden. Keine Rekursion erforderlich:
$(function() {
var $textNodes = $("#test, #test *").contents().filter(function() {
return this.nodeType === Node.TEXT_NODE;
});
/*
* for testing
*/
$textNodes.each(function() {
console.log(this);
});
});
div { margin-left: 1em; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="test">
child text 1<br>
child text 2
<div>
grandchild text 1
<div>grand-grandchild text 1</div>
grandchild text 2
</div>
child text 3<br>
child text 4
</div>
Mit der akzeptierten Filterfunktion erhielt ich eine Menge leerer Textknoten. Wenn Sie nur an der Auswahl von Textknoten interessiert sind, die keine Leerzeichen enthalten, fügen Sie eine nodeValue
Bedingung für Ihre filter
Funktion, wie eine einfache $.trim(this.nodevalue) !== ''
:
$('element')
.contents()
.filter(function(){
return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
});
Oder um seltsame Situationen zu vermeiden, in denen der Inhalt wie ein Leerzeichen aussieht, es aber nicht ist (z. B. der weiche Bindestrich ­
Zeichen, Zeilenumbrüche \n
, Tabulatoren usw.), können Sie versuchen, einen regulären Ausdruck zu verwenden. Zum Beispiel, \S
passt auf alle Zeichen, die keine Leerzeichen sind:
$('element')
.contents()
.filter(function(){
return this.nodeType === 3 && /\S/.test(this.nodeValue);
});
- See previous answers
- Weitere Antworten anzeigen