it-swarm.com.de

Verwenden von .text (), um nur Text abzurufen, der nicht in untergeordneten Tags verschachtelt ist

Wenn ich HTML so habe:

<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>

Ich versuche, .text() zu verwenden, um nur die Zeichenfolge "Dies ist etwas Text" abzurufen, aber wenn ich $('#list-item').text() sagen würde, bekomme ich "Dies ist etwas textFirst spanSecond span text".

Gibt es eine Möglichkeit, den Freitext innerhalb eines Tags zu erhalten (und möglicherweise über etwas wie .text("") zu entfernen) und nicht den Text innerhalb der untergeordneten Tags?

Das HTML wurde nicht von mir geschrieben, daher muss ich damit arbeiten. Ich weiß, dass es einfach wäre, den Text beim Schreiben der HTML-Datei in Tags einzubetten, aber auch hier ist die HTML-Datei vorab geschrieben.

329
MegaMatt

Diese wiederverwendbare Implementierung, die auf der clone()-Methode basiert, fand here

Code zur einfachen Referenz:

$("#foo")
    .clone()    //clone the element
    .children() //select all the children
    .remove()   //remove all the children
    .end()  //again go back to selected element
    .text();
465
DotNetWala

Einfache antwort:

$("#listItem").contents().filter(function(){ 
  return this.nodeType == 3; 
})[0].nodeValue = "The text you want to replace with" 
325
macio.Jun

Dies scheint mir der Fall einer übermäßigen Verwendung von Jquery zu sein. Im Folgenden wird der Text erfasst, wobei die anderen Knoten ignoriert werden:

document.getElementById("listItem").childNodes[0];

Sie müssen das kürzen, aber Sie bekommen in einer einfachen Zeile das, was Sie möchten.

EDIT

Das obige wird den text-Knoten erhalten. Um den eigentlichen Text zu erhalten, verwenden Sie Folgendes:

document.getElementById("listItem").childNodes[0].nodeValue;
121
rg88

Einfacher und schneller:

$("#listItem").contents().get(0).nodeValue
50
WakeupMorning

Ähnlich der akzeptierten Antwort, aber ohne Klonen:

$("#foo").contents().not($("#foo").children()).text();

Und hier ist ein jQuery-Plugin für diesen Zweck:

$.fn.immediateText = function() {
    return this.contents().not(this.children()).text();
};

So verwenden Sie dieses Plugin:

$("#foo").immediateText(); // get the text without children
24
DUzun

ist nicht der Code:

var text  =  $('#listItem').clone().children().remove().end().text();

nur um jQuery willen um jQuery zuliebe? Wenn für einfache Operationen so viele verkettete Befehle und diese (unnötige) Verarbeitung erforderlich sind, ist es vielleicht an der Zeit, eine jQuery-Erweiterung zu schreiben:

(function ($) {
    function elementText(el, separator) {
        var textContents = [];
        for(var chld = el.firstChild; chld; chld = chld.nextSibling) {
            if (chld.nodeType == 3) { 
                textContents.Push(chld.nodeValue);
            }
        }
        return textContents.join(separator);
    }
    $.fn.textNotChild = function(elementSeparator, nodeSeparator) {
    if (arguments.length<2){nodeSeparator="";}
    if (arguments.length<1){elementSeparator="";}
        return $.map(this, function(el){
            return elementText(el,nodeSeparator);
        }).join(elementSeparator);
    }
} (jQuery));

anrufen:

var text = $('#listItem').textNotChild();

die Argumente sind für den Fall, dass ein anderes Szenario auftritt, z

<li>some text<a>more text</a>again more</li>
<li>second text<a>more text</a>again more</li>

var text = $("li").textNotChild(".....","<break>");

text wird Wert haben:

some text<break>again more.....second text<break>again more
7
Brent

Es muss etwas sein, das auf die Bedürfnisse zugeschnitten ist, die von der Struktur abhängen, der Sie präsentiert werden. Für das von Ihnen bereitgestellte Beispiel funktioniert dies:

$(document).ready(function(){
     var $tmp = $('#listItem').children().remove();
     $('#listItem').text('').append($tmp);
});

Demo: http://jquery.nodnod.net/cases/2385/run

Es ist jedoch ziemlich abhängig davon, ob das Markup dem von Ihnen geposteten ähnlich ist.

6
c_harm

Versuche dies:

$('#listItem').not($('#listItem').children()).text()
6
pbjk
$($('#listItem').contents()[0]).text()

Kurze Variante von Stuart Antwort.

oder mit get()

$($('#listItem').contents().get(0)).text()
4
galeksandrp
jQuery.fn.ownText = function () {
    return $(this).contents().filter(function () {
        return this.nodeType === Node.TEXT_NODE;
    }).text();
};
3
Brave Dolphin

Ich nehme an, dies wäre auch eine gute Lösung - wenn Sie den Inhalt aller Textknoten erhalten möchten, die direkte untergeordnete Elemente des ausgewählten Elements sind.

$(selector).contents().filter(function(){ return this.nodeType == 3; }).text();

Hinweis: In der jQuery-Dokumentation wird zur Erklärung der Inhaltsfunktion ein ähnlicher Code verwendet: https://api.jquery.com/contents/

P.S. Es gibt auch einen etwas hässlicheren Weg, dies zu tun, aber dies zeigt detaillierter, wie die Dinge funktionieren, und ermöglicht ein benutzerdefiniertes Trennzeichen zwischen Textknoten (vielleicht möchten Sie dort einen Zeilenumbruch).

$(selector).contents().filter(function(){ return this.nodeType == 3; }).map(function() { return this.nodeValue; }).toArray().join("");
2
mvmn

Dies ist eine alte Frage, aber die beste Antwort ist sehr ineffizient. Hier ist eine bessere Lösung:

$.fn.myText = function() {
    var str = '';

    this.contents().each(function() {
        if (this.nodeType == 3) {
            str += this.textContent || this.innerText || '';
        }
    });

    return str;
};

Und mach einfach das:

$("#foo").myText();
2
rotaercz

Wenn die Position index des Textknotens zwischen seinen gleichgeordneten Elementen festgelegt ist, können Sie verwenden

$('parentselector').contents().eq(index).text()
0
inarilo

Genau wie die Frage versuchte ich, Text zu extrahieren, um den Text durch einen regulären Ausdruck auszutauschen, bekam jedoch Probleme, bei denen auch meine inneren Elemente (z. B. <i>, <div>, <span> usw.) entfernt wurden.

Der folgende Code scheint gut zu funktionieren und löste alle meine Probleme.

Einige der Antworten werden hier verwendet, insbesondere aber wird der Text nur ersetzt, wenn das Element nodeType === 3 ist.

$(el).contents().each(function() { 
  console.log(" > Content: %s [%s]", this, (this.nodeType === 3));

  if (this.nodeType === 3) {
    var text = this.textContent;
    console.log(" > Old   : '%s'", text);

    regex = new RegExp("\\[\\[" + rule + "\\.val\\]\\]", "g");
    text = text.replace(regex, value);

    regex = new RegExp("\\[\\[" + rule + "\\.act\\]\\]", "g");
    text = text.replace(regex, actual);

    console.log(" > New   : '%s'", text);
    this.textContent = text;
  }
});

Was oben beschrieben ist, durchläuft alle Elemente des angegebenen el (das einfach mit $("div.my-class[name='some-name']"); abgerufen wurde. Bei jedem inneren Element werden diese Elemente grundsätzlich ignoriert. Für jeden Teil des Textes (wie von if (this.nodeType === 3) festgelegt) wird nur die Regex-Ersetzung angewendet zu diesen Elementen.

Der this.textContent = text-Teil ersetzt einfach den ersetzten Text, den ich in meinem Fall nach Token wie [[min.val]], [[max.val]] usw. suche.

Dieser kurze Code-Auszug hilft jedem, der versucht, das zu tun, was die Frage stellt, und noch ein bisschen mehr.

0
Jeach

Ich schlage vor, mit createTreeWalker nach allen Textelementen zu suchen, die nicht mit HTML-Elementen verbunden sind (diese Funktion kann zur Erweiterung von jQuery verwendet werden):

function textNodesOnlyUnder(el) {
  var resultSet = [];
  var n = null;
  var treeWalker  = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, function (node) {
    if (node.parentNode.id == el.id && node.textContent.trim().length != 0) {
      return NodeFilter.FILTER_ACCEPT;
    }
    return NodeFilter.FILTER_SKIP;
  }, false);
  while (n = treeWalker.nextNode()) {
    resultSet.Push(n);
  }
  return resultSet;
}



window.onload = function() {
  var ele = document.getElementById('listItem');
  var textNodesOnly = textNodesOnlyUnder(ele);
  var resultingText = textNodesOnly.map(function(val, index, arr) {
    return 'Text element N. ' + index + ' --> ' + val.textContent.trim();
  }).join('\n');
  document.getElementById('txtArea').value = resultingText;
}
<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>
<textarea id="txtArea" style="width: 400px;height: 200px;"></textarea>

0
gaetanoM

Ich habe eine spezifische Lösung gefunden, die wesentlich effizienter sein sollte als das Klonen und Modifizieren des Klons. Diese Lösung funktioniert nur mit den beiden folgenden Vorbehalten, sollte jedoch effizienter sein als die derzeit akzeptierte Lösung:

  1. Sie erhalten nur den Text
  2. Der zu extrahierende Text steht vor den untergeordneten Elementen

Nachdem dies gesagt wurde, hier ist der Code:

// 'element' is a jQuery element
function getText(element) {
  var text = element.text();
  var childLength = element.children().text().length;
  return text.slice(0, text.length - childLength);
}
0
Yu Jiang Tham

legen Sie es einfach in einen <p> oder <font> und holen Sie sich $ ('# listItem font'). text ()

Das erste, was mir in den Sinn kam

<li id="listItem">
    <font>This is some text</font>
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>
0
Dorjan