it-swarm.com.de

Wie wähle ich Textknoten mit jQuery aus?

Ich möchte alle untergeordneten Textknoten eines Elements als jQuery-Auflistung erhalten. Wie geht das am besten?

378

jQuery hat dafür keine komfortable Funktion. Sie müssen contents() kombinieren, das nur untergeordnete Knoten enthält, aber Textknoten enthält, mit find(), das alle untergeordneten Elemente enthält, jedoch keine Textknoten. Folgendes habe ich mir ausgedacht:

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, funktioniert der obige Code nicht. Um dies zu beheben, ersetzen Sie addBack() durch andSelf() . andSelf() ist zu Gunsten von addBack() ab 1.8 veraltet.

Dies ist im Vergleich zu reinen DOM-Methoden etwas ineffizient und muss ein hässlicher Workaround für die Überladung der contents() -Funktion durch jQuery (dank @rabidsnail in den Kommentaren, um darauf hinzuweisen) enthalten. Hier handelt es sich also um eine Nicht-jQuery-Lösung mit einer einfachen rekursiven Funktion. Der Parameter includeWhitespaceNodes steuert, ob Whitespace-Textknoten in der Ausgabe enthalten sind oder nicht (in jQuery werden sie automatisch herausgefiltert).

Update: Fehler behoben, wenn includeWhitespaceNodes falsch 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);
255
Tim Down

Jauco hat eine gute Lösung in einem Kommentar gepostet, also kopiere ich sie hier:

$(elem)
  .contents()
  .filter(function() {
    return this.nodeType === 3; //Node.TEXT_NODE
  });
207
$('body').find('*').contents().filter(function () { return this.nodeType === 3; });
16
He Nrik

jQuery.contents() kann verwendet werden mit jQuery.filter um alle untergeordneten Textknoten zu finden. Mit einem kleinen Dreh finden Sie auch Textknoten für Enkelkinder. 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>

jsFiddle

6
Salman A

Ich habe viele leere Textknoten mit der akzeptierten Filterfunktion erhalten. Wenn Sie nur Textknoten mit Leerzeichen auswählen möchten, fügen Sie eine nodeValue-Bedingung zu Ihrer filter-Funktion hinzu, z. B. eine einfache $.trim(this.nodevalue) !== '':

$('element')
    .contents()
    .filter(function(){
        return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
    });

http://jsfiddle.net/ptp6m97v/

Oder um ungewöhnliche Situationen zu vermeiden, in denen der Inhalt wie ein Leerzeichen aussieht, jedoch nicht (z. B. der weiche Bindestrich &shy; Zeichen, Zeilenumbruch \n, Tabulatoren usw.) können Sie versuchen, einen regulären Ausdruck zu verwenden. Beispielsweise, \S stimmt mit allen Nicht-Leerzeichen überein:

$('element')
        .contents()
        .filter(function(){
            return this.nodeType === 3 && /\S/.test(this.nodeValue);
        });
4
Alex W

Wenn Sie davon ausgehen können, dass alle untergeordneten Elemente entweder Elementknoten oder Textknoten sind, ist dies eine Lösung.

So rufen Sie alle untergeordneten Textknoten als jquery-Auflistung ab:

$('selector').clone().children().remove().end().contents();

So erhalten Sie eine Kopie des ursprünglichen Elements, wenn untergeordnete Elemente, die kein Text sind, entfernt wurden:

$('selector').clone().children().remove().end();
3
colllin

Aus irgendeinem Grund hat contents() bei mir nicht funktioniert. Wenn es also bei Ihnen nicht funktioniert hat, habe ich eine Lösung gefunden, die ich erstellt habe. jQuery.fn.descendants mit der Option, Textknoten einzuschließen oder nicht

Verwendung


Holen Sie sich alle Nachkommen einschließlich Textknoten und Elementknoten

jQuery('body').descendants('all');

Alle Nachkommen abrufen, die nur Textknoten zurückgeben

jQuery('body').descendants(true);

Alle Nachkommen abrufen, die nur Elementknoten zurückgeben

jQuery('body').descendants();

Coffeescript Original :

jQuery.fn.descendants = ( textNodes ) ->

    # if textNodes is 'all' then textNodes and elementNodes are allowed
    # if textNodes if true then only textNodes will be returned
    # if textNodes is not provided as an argument then only element nodes
    # will be returned

    allowedTypes = if textNodes is 'all' then [1,3] else if textNodes then [3] else [1]

    # nodes we find
    nodes = []


    Dig = (node) ->

        # loop through children
        for child in node.childNodes

            # Push child to collection if has allowed type
            nodes.Push(child) if child.nodeType in allowedTypes

            # Dig through child if has children
            Dig child if child.childNodes.length


    # loop and Dig through nodes in the current
    # jQuery object
    Dig node for node in this


    # wrap with jQuery
    return jQuery(nodes)

Drop In Javascript Version

var __indexOf=[].indexOf||function(e){for(var t=0,n=this.length;t<n;t++){if(t in this&&this[t]===e)return t}return-1}; /* indexOf polyfill ends here*/ jQuery.fn.descendants=function(e){var t,n,r,i,s,o;t=e==="all"?[1,3]:e?[3]:[1];i=[];n=function(e){var r,s,o,u,a,f;u=e.childNodes;f=[];for(s=0,o=u.length;s<o;s++){r=u[s];if(a=r.nodeType,__indexOf.call(t,a)>=0){i.Push(r)}if(r.childNodes.length){f.Push(n(r))}else{f.Push(void 0)}}return f};for(s=0,o=this.length;s<o;s++){r=this[s];n(r)}return jQuery(i)}

Nicht minimierte Javascript-Version: http://Pastebin.com/cX3jMfuD

Dies ist ein Cross-Browser, ein kleines Array.indexOf polyfill ist im Code enthalten.

2
iConnor

Kann auch so gemacht werden:

var textContents = $(document.getElementById("ElementId").childNodes).filter(function(){
        return this.nodeType == 3;
});

Der obige Code filtert die textNodes von direkten untergeordneten Knoten eines bestimmten Elements.

1
Mr_Green

wenn Sie alle Tags entfernen möchten, versuchen Sie dies

Funktion:

String.prototype.stripTags=function(){
var rtag=/<.*?[^>]>/g;
return this.replace(rtag,'');
}

Verwendung:

var newText=$('selector').html().stripTags();
0
Rahen Rangan

Ich hatte das gleiche Problem und löste es mit:

Code:

$.fn.nextNode = function(){
  var contents = $(this).parent().contents();
  return contents.get(contents.index(this)+1);
}

Verwendungszweck:

$('#my_id').nextNode();

Ist wie next(), gibt aber auch die Textknoten zurück.

0
Guillermo

Für mich hat es den Anschein, als würde das einfache alte .contents() funktionieren, um die Textknoten zurückzugeben. Sie müssen nur vorsichtig mit Ihren Selektoren umgehen, damit Sie wissen, dass es sich um Textknoten handelt.

Dies hat beispielsweise den gesamten Textinhalt der TDs in meiner Tabelle mit pre -Tags umbrochen und hatte keine Probleme.

jQuery("#resultTable td").content().wrap("<pre/>")
0
davenpcj