.text ()를 사용하여 자식 태그에 중첩되지 않은 텍스트 만 검색


386

내가 이런 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은 미리 작성되어 있습니다.


아직 의견을 말할만큼 평판이 충분하지 않고 지식이 손실되기를 원하지 않기 때문에 (다른 사람에게 도움이되기를 바랍니다), macio.Jun 'answer , RegExp 및 iStranger' 의 조합으로 textNode를 HTML바꿉니다. 자바 스크립트로? 텍스트 전용 노드에서 문자열을 검색하고 모든 항목을 링크로 바꿀 수있었습니다.
JDQ

답변:


509

부모 요소 내부의 텍스트 만 가져 오기 위해 여기 에서 clone()찾은 메소드를 기반으로하는 재사용 가능한 구현이 마음에 들었습니다 .

쉽게 참조 할 수 있도록 제공된 코드 :

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

5
이 솔루션을 사용하면 자식이없는 텍스트 만 얻을 수 있지만 텍스트 만 바꿀 수는 없습니다.
BenRoe

1
나는 1 가지를 얻지 못한다 : .end ()가 선택된 요소로 돌아 가면 text ()가 자식 요소와 함께 원본 텍스트를 복사해야합니다. 그러나 실제로는 조작 된 클론의 텍스트가 복사되고 있음을 알 수 있습니다. 그래서 end ()는 clone ()으로 돌아갑니다.

68
이것은 정말 비효율적 인 방법입니다
billyonecan

5
@billyonecan, 더 효율적인 방법을 제안 할 수 있습니까? 이것은 "깨끗하고"짧기 때문에 매력적입니다. 당신은 무엇을 제안합니까?
derekmx271


364

간단한 답변 :

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

38
불필요한 데이터 구조를 생성하지 않는 효율적인 답변이 덜 무서운 답변만큼 투표되지 않는 이유를 이해하지 못합니다. 내가 할 수 있다면 +5.
Steven Lu

16
간단하고 효율적인 답변
Paul Carroll

9
이것은 더 효율적일뿐만 아니라 정확합니다! 이 솔루션은 텍스트가 자식 요소 사이에 흩어져있는 상황에 적합합니다. +5
Kyryll Tenin Baum

15
더 명확하게하기 위해 IE8 +를 사용 this.nodeType == Node.TEXT_NODE하는 경우 대신 대신 사용할 수 있습니다 this.nodeType == 3. IMO를 읽고 이해하기가 더 쉽습니다.
NorTicUs

8
텍스트가없는 것으로 사용하면 중단됩니다. 이것을 함수로 사용하고 텍스트가 있거나 없을 수있는 시나리오가있는 경우 .contents().filter(...), 로컬 변수로 호출을 캡처 하고 길이를 확인하십시오. var text = $(this).contents().filter(...); if (text.length) { return text[0].nodeValue; } return "";
Carl Bussema

157

이것은 jquery를 과도하게 사용하는 경우처럼 보입니다. 다음은 다른 노드를 무시하고 텍스트를 가져옵니다.

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

당신은 그것을 다듬어야하지만 하나의 쉬운 라인에서 원하는 것을 얻습니다.

편집하다

위의 텍스트 노드 를 얻을 것이다 . 실제 텍스트를 얻으려면 다음을 사용하십시오.

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

31
가장 좋은 대답은이 플러그인 또는 10 개의 jQuery 호출 체인을 필요로하지 않습니다. $('.foo')[0].childNodes[0].nodeValue.trim()
raine

5
텍스트 내용이 여러 노드 (예 : crlf, text, crlf 시퀀스)로 분할되면 어떻게됩니까? ua에 의해 생성 된 DOM이 가장 간단한 구조를 사용할 것이라는 보장이 있습니까?
collapsar

5
전적으로 가장 좋은 대답은 ... 왜 다른 사람들이 때때로 jQuery를 과도하게 사용합니까?
ncubica

11
<div id = "listItem"> 원하는 <span> 기타 </ span> </ div>의 경우에만 작동합니다. <div id = "listItem"> <span> 다른 </ span> 원하는 텍스트 </ div>에는 작동하지 않습니다.
Spencer

1
때때로 당신은 없습니다 document. 를 사용하여 여기에 왔습니다 cheerio.
플래시


28

허용되는 답변과 비슷하지만 복제하지 않은 경우 :

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

이 목적을위한 jQuery 플러그인은 다음과 같습니다.

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

이 플러그인을 사용하는 방법은 다음과 같습니다.

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

t.children ()에서 t는 무엇입니까?
FrEaKmAn

이것은 pbjk가 Jan'15에서 썼던 것의 복제 솔루션입니다 ... 그럼에도 불구하고-그것은 좋아 보입니다.
Oskar Holmkratz

1
사실, @Oskar는 아닙니다. 여기서 .contents()중요한 부분입니다!
DUzun

노드가 ID를 사용하지 않으면 나쁜 해결책입니다.
AndroidDev

3
@AndroidDev 항상 선택기를 원하는대로 바꿀 수 있습니다. 이것은 단지 기술을 설명하기위한 것입니다! 또한 ID 없이도 작동하는 플러그인 버전을 추가했습니다
DUzun

8

코드가 아닙니다 :

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

1
좋은. 다음 버전의 jQuery에 대한 풀 요청을 만드는 것은 어떻습니까?
Jared Tomaszewski

8

이 시도:

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

6

제시된 구조에 따라 필요에 맞게 조정해야합니다. 제공 한 예제의 경우 다음과 같이 작동합니다.

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

데모 : http://jquery.nodnod.net/cases/2385/run

그러나 게시 한 것과 비슷한 마크 업에 상당히 의존합니다.


2
미래의 독자는 조심하십시오 :이 답변의 코드는 실제 요소의 어린이를 죽입니다. clone의도 된 효과가 아닌 경우 여기에서이 방법을 사용해야합니다 .
Mahn

아래 @DotNetWala의 답변 이며이 대신 사용해야합니다. 또는 적어도 .detach()대신 메소드를 사용하십시오 .remove().
Don McCurdy 2016 년


4
jQuery.fn.ownText = function () {
    return $(this).contents().filter(function () {
        return this.nodeType === Node.TEXT_NODE;
    }).text();
};

1
이 코드 스 니펫에 감사드립니다. 즉각적인 도움이 될 수 있습니다. 적절한 설명 이것이 문제에 대한 좋은 해결책 인지 보여줌으로써 교육적 가치를 크게 향상시킬 것이며 , 유사하지만 동일하지 않은 질문을 가진 미래 독자들에게 더 유용 할 것입니다. 제발 편집 설명을 추가하고, 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Toby Speight

3

이것은 오래된 질문이지만 최고의 대답은 매우 비효율적입니다. 더 나은 해결책은 다음과 같습니다.

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

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

    return str;
};

그리고 그냥 이렇게하십시오 :

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

3

선택한 요소의 직접적인 자식 인 모든 텍스트 노드의 내용을 얻으려면이 방법도 훌륭한 해결책이라고 생각합니다.

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

참고 : jQuery 문서는 비슷한 코드를 사용하여 내용 기능을 설명합니다 : https://api.jquery.com/contents/

추신 : 그것을 수행하는 조금 더 추한 방법이 있지만, 이것은 일이 어떻게 작동하는지 더 깊이 보여주고 텍스트 노드 사이에 사용자 정의 구분 기호를 허용합니다 (줄 바꿈을 원할 수도 있습니다)

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

1

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>


1

index텍스트 노드 의 위치 가 해당 형제 사이에서 고정되어 있으면

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

1

얼마나 유연하고 많은 사례를 다루어야하는지 잘 모르겠지만 예를 들어 텍스트가 항상 첫 번째 HTML 태그 앞에 오는 경우 – 첫 번째 태그에서 내부 HTML을 분할하여 이전 HTML을 가져와야하는 이유는 무엇입니까?

$('#listItem').html().split('<span')[0]; 

더 넓다면 필요할 수도 있습니다

$('#listItem').html().split('<')[0]; 

그리고 두 마커 사이에 텍스트가 필요한 경우, 한 가지 후에 다른 것보다 먼저, (unested) 같은 작업을 수행하고 if 문을 사용하여 시작 또는 끝 마커 또는 둘 다를 충분히 유연하게 만들 수 있습니다. :

var startMarker = '';// put any starting marker here
var endMarker = '<';// put the end marker here
var myText = String( $('#listItem').html() );
// if the start marker is found, take the string after it
myText = myText.split(startMarker)[1];        
// if the end marker is found, take the string before it
myText = myText.split(endMarker)[0];
console.log(myText); // output text between the first occurrence of the markers, assuming both markers exist.  If they don't this will throw an error, so some if statements to check params is probably in order...

나는 일반적으로 이와 같은 유용한 것들을 위해 유틸리티 함수를 만들고, 오류를 없애고, 이러한 유형의 문자열 조작을 다시 작성하고 null 참조를 위험에 빠뜨리는 대신 항상 한 번 확실하게 의존합니다. 그렇게하면 함수를 재사용 할 수 있습니다 많은 프로젝트에서 문자열 참조에 정의되지 않은 참조 오류가있는 이유를 디버깅하는 데 다시 시간을 낭비하지 않아도됩니다. 가장 짧은 1 줄 코드는 아니지만 유틸리티 기능을 갖춘 후에는 한 줄입니다. 코드의 대부분은 오류를 피하기 위해 매개 변수를 처리하거나 처리하지 않습니다. :)

예를 들면 다음과 같습니다.

/**
* Get the text between two string markers.
**/
function textBetween(__string,__startMark,__endMark){
    var hasText = typeof __string !== 'undefined' && __string.length > 0;
    if(!hasText) return __string;
    var myText = String( __string );
    var hasStartMarker = typeof __startMark !== 'undefined' && __startMark.length > 0 && __string.indexOf(__startMark)>=0;
    var hasEndMarker =  typeof __endMark !== 'undefined' && __endMark.length > 0 && __string.indexOf(__endMark) > 0;
    if( hasStartMarker )  myText = myText.split(__startMark)[1];
    if( hasEndMarker )    myText = myText.split(__endMark)[0];
    return myText;
}

// now with 1 line from now on, and no jquery needed really, but to use your example:
var textWithNoHTML = textBetween( $('#listItem').html(), '', '<'); // should return text before first child HTML tag if the text is on page (use document ready etc)

텍스트를 바꿔야한다면 $('#listItem').html( newHTML ); 여기서 newHTML은 이미 제거 된 텍스트가있는 변수입니다.
OG Sean


0

복제본 복제 및 수정보다 훨씬 효율적인 특정 솔루션을 생각해 냈습니다. 이 솔루션은 다음 두 가지 예약에서만 작동하지만 현재 승인 된 솔루션보다 효율적이어야합니다.

  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

그냥 질문처럼, 나는 텍스트의 일부 정규식 치환을하기 위해 추출 텍스트하려고했지만 문제를 얻고 있었다 어디에 내 내부 요소 (예 : <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;
  }
});

위의 내용은 주어진 모든 요소를 ​​반복하는 것입니다 el(간단히로 얻은 것입니다 $("div.my-class[name='some-name']");. 각 내부 요소에 대해 기본적으로 요소를 무시합니다. 텍스트의 각 부분에 대해 (if (this.nodeType === 3) ) 해당 요소에만 정규식 대체를 적용합니다. .

this.textContent = text부분은 단순히 내 경우에는, 내가 좋아하는 토큰을 찾고 있었다 치환체의 텍스트, 대체 [[min.val]], [[max.val]]

이 짧은 코드 발췌문은 질문이하는 일을하려고하는 사람에게 도움이 될 것입니다 ... 그리고 조금 더.


-1

그냥 넣어 <p> 또는에<font> $ ( '# listItem font'). text ()

가장 먼저 떠오른 것은

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

6
내가 사용하는 코드가 내가 만든 것이 아니기 때문에 무료 텍스트를 태그에 넣는 것을 제어 할 수 없습니다. 해당 텍스트 만 잡을 수 있다면 텍스트를 제거하고 그 주위에 태그로 바꾸거나 원하는 것을 할 수 있습니다. 그러나 html은 이미 미리 작성되었습니다.
MegaMatt

그래. 그런 다음 결과를 필터링해야한다고 생각합니다. 죄송합니다.
Dorjan

-1

당신은 이것을 시도 할 수 있습니다

alert(document.getElementById('listItem').firstChild.data)

-2

innerHTML과 innerText가 동일한 지 확인하려면 추가 조건을 사용하십시오. 그러한 경우에만 텍스트를 바꾸십시오.

$(function() {
$('body *').each(function () {
    console.log($(this).html());
    console.log($(this).text());
    if($(this).text() === "Search" && $(this).html()===$(this).text())  {
        $(this).html("Find");
    }
})
})

http://jsfiddle.net/7RSGh/


-2

결과를 다듬 으려면 DotNetWala를 다음과 같이 사용하십시오.

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

document.getElementById("listItem").childNodes[0]jQuery의 trim () 에서는 짧은 버전을 사용하는 것이 작동하지 않는다는 것을 알았습니다 .


3
document.getElementById("listItem").childNodes[0]일반 자바 스크립트 이기 때문에 jQuery 함수로 감싸 야합니다.$(document.getElementById("listItem").childNodes[0]).trim()
Red Taz

알겠습니다. ㅋ. 감사!
Marion Go

1
이것은 DotNetWala의 답변 과 거의 동일합니다 . 당신이 한 모든 것이 .trim()끝에 추가되었습니다 . 이 답변이 필요합니까?
모든 노동자는 필수입니다

-3

나는 jquery 전문가가 아니지만 어떻습니까?

$('#listItem').children().first().text()

1
jquery 전문가를 알고 있다면 다른 답변을 먼저 읽어서 더 많은 전문가가되지 않는 이유는 무엇입니까? 좋은 아이디어.
Oskar Holmkratz

-4

이것은 테스트되지 않았지만 다음과 같이 시도해 볼 수 있습니다.

 $('#listItem').not('span').text();

http://api.jquery.com/not/


3
와 동일하기 때문 $('#listItem').text()입니다. #listItem되지 <span>때문에 추가 not('span')아무것도하지 않습니다.
Thomas Higginbotham
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.