web-dev-qa-db-ja.com

子タグにネストされてないテキストのみを取得するための.text()の使用

私はこのようなHTMLがあれば:

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

.text()を使用して文字列 "This is some text"だけを取得しようとしていますが、$('#list-item').text()と言うと、 "これはtextFirst span textSecond span text"となります。

子タグ内のテキストではなく、タグ内のフリーテキストだけを取得する(そしておそらくは.text("")のような方法で削除する)方法はありますか。

HTMLは私によって書かれたのではないので、これは私が扱わなければならないものです。 HTMLを書くときにテキストをタグで囲むのが簡単であることを私は知っています、しかしまた、HTMLは事前に書かれています。

349
MegaMatt

clone()メソッドをベースにしたこの再利用可能な実装 ここ を親要素の内側のテキストだけを取得するのが好きでした。

簡単に参照できるように提供されたコード:

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

簡単な答え:

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

これは私にjqueryを使いすぎるケースのようです。以下は、他のノードを無視してテキストを取得します。

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

あなたはそれをトリミングする必要がありますが、それはあなたが1つの簡単な行であなたが望むものをあなたに導きます。

EDIT

上記はテキストノードを取得します。実際のテキストを取得するには、これを使います。

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

より簡単かつ迅速に

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

受け入れられている答えと似ていますが、複製はしていません。

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

そして、これがこの目的のためのjQueryプラグインです。

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

これがこのプラグインの使い方です。

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

これを試して:

$('#listItem').not($('#listItem').children()).text()
8
pbjk

コードではありません:

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

jQueryのためだけにjQueryになりませんか?単純な操作に多くの連鎖コマンドとそれほど多くの(不要な)処理が含まれる場合は、おそらくjQuery拡張機能を作成する時が来たでしょう。

(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));

呼び出すために:

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

引数は、次のような異なるシナリオが発生した場合に備えています。

<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>");

テキストは値を持ちます。

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

それはニーズに合わせたものである必要があります。それはあなたが提示した構造に依存します。あなたが提供した例では、これは動作します:

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

デモ: http://jquery.nodnod.net/cases/2385/run

しかし、それはマークアップがあなたが投稿したものと似ていることにかなり依存しています。

6
c_harm
$($('#listItem').contents()[0]).text()

Stuart answer。 の短い変形

または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

選択した要素の直接の子であるすべてのテキストノードのコンテンツを取得したい場合は、これもすばらしい解決策になると思います。

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

注:jQueryの資料では、コンテンツ機能を説明するために同様のコードを使用しています。 https://api.jquery.com/contents/

P.Sこれを行うには少し厄介な方法もありますが、これは物事がどのように機能するかをより深く示し、テキストノード間のカスタムセパレータを可能にします(多分あなたはそこに改行を望むでしょう)

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

これは古い質問ですが、一番の答えは非常に非効率的です。これがより良い解決策です。

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

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

    return str;
};

そしてちょうどこれをしなさい:

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

テキストノードの位置indexがその兄弟の間で固定されている場合は、次のようにします。

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

質問と同じように、テキストを正規表現で置換するためにテキストを抽出しようとしましたが、内部の要素(<i><div><span>など)も削除されるという問題が発生していました。

次のコードはうまくいって、私のすべての問題を解決したようです。

ここで提供されている回答のいくつかを使用しますが、特に、要素がnodeType === 3である場合にのみテキストを置き換えます。

$(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;
  }
});

上記のことは、($("div.my-class[name='some-name']");で単純に取得された)与えられたelのすべての要素をループすることです。各内部要素については、基本的にそれらを無視します。(if (this.nodeType === 3)によって決定される)それらの要素に。

this.textContent = textの部分は置換されたテキストを単に置き換えるもので、私の場合は[[min.val]][[max.val]]などのようなトークンを探していました。

この短いコードの抜粋は、質問が求めていたことをやろうとしている人をだれかが手助けするでしょう...そしてもう少し。

0
Jeach

私は createTreeWalker を使用して、HTML要素に結び付けられていないすべてのテキスト要素を検索することを提案します(この関数はjQueryを拡張するために使用できます)。

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

私はクローンのクローン作成と修正よりもはるかに効率的であるべき特定の解決策を思い付きました。この解決策は、次の2つの予約でのみ機能しますが、現在受け入れられている解決策よりも効率的です。

  1. あなたはテキストだけを手に入れています
  2. 抽出したいテキストは子要素の前にあります

とはいえ、これがコードです。

// '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

<p>または<font>に入れて、その$( '#listItem font')をつかむだけです。

最初に思い浮かんだこと

<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