[javascript] 요소의 텍스트 노드를 얻는 방법은 무엇입니까?

<div class="title">
   I am text node
   <a class="edit">Edit</a>
</div>

“I am text node”를 얻고 싶습니다. “edit”태그를 제거하고 싶지 않으며 크로스 브라우저 솔루션이 필요합니다.



답변

var text = $(".title").contents().filter(function() {
  return this.nodeType == Node.TEXT_NODE;
}).text();

contents선택한 요소를 가져 와서 필터 기능을 적용합니다. 필터 함수는 텍스트 노드 (예 :가있는 노드 nodeType == Node.TEXT_NODE) 만 반환합니다 .


답변

다음을 사용하여 첫 번째 childNode의 nodeValue를 얻을 수 있습니다.

$('.title')[0].childNodes[0].nodeValue

http://jsfiddle.net/TU4FB/


답변

요소의 첫 번째 텍스트 노드 값을 얻으려면 다음 코드가 작동합니다.

var oDiv = document.getElementById("MyDiv");
var firstText = "";
for (var i = 0; i < oDiv.childNodes.length; i++) {
    var curNode = oDiv.childNodes[i];
    if (curNode.nodeName === "#text") {
        firstText = curNode.nodeValue;
        break;
    }
}

여기에서 실제 동작을 볼 수 있습니다 : http://jsfiddle.net/ZkjZJ/


답변

“복잡”하거나 깊게 중첩 된 요소에 유용 할 수있는 또 다른 기본 JS 솔루션은 NodeIterator 를 사용하는 것 입니다. 넣어 NodeFilter.SHOW_TEXT으로 반복 요소의 바로 텍스트 노드의 아이를 통해 두 번째 인수 ( “whatToShow에”)로합니다.

var root = document.querySelector('p'),
    iter = document.createNodeIterator(root, NodeFilter.SHOW_TEXT),
    textnode;

// print all text nodes
while (textnode = iter.nextNode()) {
  console.log(textnode.textContent)
}
<p>
<br>some text<br>123
</p>

를 사용할 수도 있습니다 TreeWalker. 둘 사이의 차이점은 NodeIterator단순한 선형 반복기이며 TreeWalker형제 및 조상을 통해 탐색 할 수도 있다는 것입니다.


답변

순수 자바 스크립트 : 미니멀리스트

우선, DOM에서 텍스트를 찾을 때 항상 이것을 명심하십시오.

MDN-DOM의 공백

이 문제는 XML / HTML의 구조에주의를 기울이게합니다.

이 순수한 JavaScript 예제에서는 다른 종류의 노드와 인터리브 될 수있는 여러 텍스트 노드가능성을 설명합니다 . 그러나 처음에는 공백에 대한 판단을 내리지 않고 필터링 작업을 다른 코드에 맡깁니다.

이 버전에서는 NodeList호출 / 클라이언트 코드에서 전달합니다 .

/**
* Gets strings from text nodes. Minimalist. Non-robust. Pre-test loop version.
* Generic, cross platform solution. No string filtering or conditioning.
*
* @author Anthony Rutledge
* @param nodeList The child nodes of a Node, as in node.childNodes.
* @param target A positive whole number >= 1
* @return String The text you targeted.
*/
function getText(nodeList, target)
{
    var trueTarget = target - 1,
        length = nodeList.length; // Because you may have many child nodes.

    for (var i = 0; i < length; i++) {
        if ((nodeList[i].nodeType === Node.TEXT_NODE) && (i === trueTarget)) {
            return nodeList[i].nodeValue;  // Done! No need to keep going.
        }
    }

    return null;
}

물론, node.hasChildNodes()먼저 테스트 하면 사전 테스트 for루프 를 사용할 필요가 없습니다 .

/**
* Gets strings from text nodes. Minimalist. Non-robust. Post-test loop version.
* Generic, cross platform solution. No string filtering or conditioning.
*
* @author Anthony Rutledge
* @param nodeList The child nodes of a Node, as in node.childNodes.
* @param target A positive whole number >= 1
* @return String The text you targeted.
*/
function getText(nodeList, target)
{
    var trueTarget = target - 1,
        length = nodeList.length,
        i = 0;

    do {
        if ((nodeList[i].nodeType === Node.TEXT_NODE) && (i === trueTarget)) {
            return nodeList[i].nodeValue;  // Done! No need to keep going.
         }

        i++;
    } while (i < length);

    return null;
}

순수 JavaScript : 견고 함

다음 함수는 getTextById()두 개의 도우미 기능을 사용 getStringsFromChildren()하고 filterWhitespaceLines().


getStringsFromChildren ()

/**
* Collects strings from child text nodes.
* Generic, cross platform solution. No string filtering or conditioning.
*
* @author Anthony Rutledge
* @version 7.0
* @param parentNode An instance of the Node interface, such as an Element. object.
* @return Array of strings, or null.
* @throws TypeError if the parentNode is not a Node object.
*/
function getStringsFromChildren(parentNode)
{
    var strings = [],
        nodeList,
        length,
        i = 0;

    if (!parentNode instanceof Node) {
        throw new TypeError("The parentNode parameter expects an instance of a Node.");
    }

    if (!parentNode.hasChildNodes()) {
        return null; // We are done. Node may resemble <element></element>
    }

    nodeList = parentNode.childNodes;
    length = nodeList.length;

    do {
        if ((nodeList[i].nodeType === Node.TEXT_NODE)) {
            strings.push(nodeList[i].nodeValue);
         }

        i++;
    } while (i < length);

    if (strings.length > 0) {
        return strings;
    }

    return null;
}

filterWhitespaceLines ()

/**
* Filters an array of strings to remove whitespace lines.
* Generic, cross platform solution.
*
* @author Anthony Rutledge
* @version 6.0
* @param textArray a String associated with the id attribute of an Element.
* @return Array of strings that are not lines of whitespace, or null.
* @throws TypeError if the textArray param is not of type Array.
*/
function filterWhitespaceLines(textArray)
{
    var filteredArray = [],
        whitespaceLine = /(?:^\s+$)/; // Non-capturing Regular Expression.

    if (!textArray instanceof Array) {
        throw new TypeError("The textArray parameter expects an instance of a Array.");
    }

    for (var i = 0; i < textArray.length; i++) {
        if (!whitespaceLine.test(textArray[i])) {  // If it is not a line of whitespace.
            filteredArray.push(textArray[i].trim());  // Trimming here is fine. 
        }
    }

    if (filteredArray.length > 0) {
        return filteredArray ; // Leave selecting and joining strings for a specific implementation. 
    }

    return null; // No text to return.
}

getTextById ()

/**
* Gets strings from text nodes. Robust.
* Generic, cross platform solution.
*
* @author Anthony Rutledge
* @version 6.0
* @param id A String associated with the id property of an Element.
* @return Array of strings, or null.
* @throws TypeError if the id param is not of type String.
* @throws TypeError if the id param cannot be used to find a node by id.
*/
function getTextById(id)
{
    var textArray = null;             // The hopeful output.
    var idDatatype = typeof id;       // Only used in an TypeError message.
    var node;                         // The parent node being examined.

    try {
        if (idDatatype !== "string") {
            throw new TypeError("The id argument must be of type String! Got " + idDatatype);
        }

        node = document.getElementById(id);

        if (node === null) {
            throw new TypeError("No element found with the id: " + id);
        }

        textArray = getStringsFromChildren(node);

        if (textArray === null) {
            return null; // No text nodes found. Example: <element></element>
        }

        textArray = filterWhitespaceLines(textArray);

        if (textArray.length > 0) {
            return textArray; // Leave selecting and joining strings for a specific implementation. 
        }
    } catch (e) {
        console.log(e.message);
    }

    return null; // No text to return.
}

다음으로 반환 값 (Array 또는 null)이 처리되어야하는 클라이언트 코드로 전송됩니다. 바라건대, 배열에는 공백 줄이 아닌 실제 텍스트의 문자열 요소가 있어야합니다.

유효한 텍스트가 있음을 올바르게 표시하려면 텍스트 노드가 필요하므로 빈 문자열 ( "")이 반환 되지 않습니다 . ( "")를 반환 하면 텍스트 노드가 존재한다는 잘못된 인상을 줄 수 있으며, 누군가가의 값을 변경하여 텍스트를 변경할 수 있다고 가정하게 할 수 있습니다 .nodeValue. 빈 문자열의 경우 텍스트 노드가 존재하지 않기 때문에 이는 거짓입니다.

예 1 :

<p id="bio"></p> <!-- There is no text node here. Return null. -->

예 2 :

<p id="bio">

</p> <!-- There are at least two text nodes ("\n"), here. -->

HTML을 간격을 두어 읽기 쉽게 만들고 싶을 때 문제가 발생합니다. 이제 사람이 읽을 수있는 유효한 텍스트가 없더라도 속성 에 줄 바꿈 ( "\n") 문자가 있는 텍스트 노드가.nodeValue 있습니다.

인간은 예제 1과 2를 기능적으로 동일한 것으로 간주합니다. 채워지기를 기다리는 빈 요소입니다. DOM은 인간의 추론과 다릅니다. 이것이 getStringsFromChildren()함수가 텍스트 노드가 존재하는지 확인하고 .nodeValue값을 배열로 수집해야하는 이유 입니다.

for (var i = 0; i < length; i++) {
    if (nodeList[i].nodeType === Node.TEXT_NODE) {
            textNodes.push(nodeList[i].nodeValue);
    }
}

예제 2에서는 두 개의 텍스트 노드가 존재하며 둘 다 ( )를 getStringFromChildren()반환합니다 . 그러나 정규식을 사용하여 순수한 공백 문자 행을 필터링합니다..nodeValue"\n"filterWhitespaceLines()

null개행 문자 ( "\n") 대신 반환하는 것이 클라이언트 / 호출 코드에 거짓말을하는 형태입니까? 인간적인 측면에서는 그렇지 않습니다. DOM 측면에서 그렇습니다. 그러나 여기서 문제는 텍스트를 편집하는 것이 아니라 텍스트를받는 것입니다. 호출 코드로 반환 할 사람 텍스트가 없습니다.

누군가의 HTML에 얼마나 많은 개행 문자가 나타날 수 있는지 결코 알 수 없습니다. “두 번째”줄 바꿈 문자를 찾는 카운터를 만드는 것은 신뢰할 수 없습니다. 존재하지 않을 수 있습니다.

물론 추가 공백이 있는 빈 요소 (예 2) 에서 텍스트편집 하는 문제 <p></p>는 단락의 태그 사이에있는 텍스트 노드 하나를 제외한 모든 요소를 ​​제거 (건너 뛰기)하여 요소에 정확한 내용이 포함되도록 할 수 있습니다. 표시해야합니다.

어쨌든, 당신이 특별한 일을하는 경우를 제외하고, 어떤 텍스트 노드의 .nodeValue속성이 당신이 편집하고 싶은 진실하고 사람이 읽을 수있는 텍스트를 가지고 있는지를 결정하는 방법이 필요합니다 . filterWhitespaceLines우리를 반쯤 가져옵니다.

var whitespaceLine = /(?:^\s+$)/; // Non-capturing Regular Expression.

for (var i = 0; i < filteredTextArray.length; i++) {
    if (!whitespaceLine.test(textArray[i])) {  // If it is not a line of whitespace.
        filteredTextArray.push(textArray[i].trim());  // Trimming here is fine. 
    }
}

이 시점에서 다음과 같은 출력이있을 수 있습니다.

["Dealing with text nodes is fun.", "Some people just use jQuery."]

이 두 문자열이 DOM에서 서로 인접 해 있다는 보장은 없으므로 두 문자열을 결합 .join()하면 부 자연스러운 합성 이 될 수 있습니다. 대신를 호출하는 코드 getTextById()에서 작업 할 문자열을 선택해야합니다.

출력을 테스트하십시오.

try {
    var strings = getTextById("bio");

    if (strings === null) {
        // Do something.
    } else if (strings.length === 1) {
        // Do something with strings[0]
    } else { // Could be another else if
        // Do something. It all depends on the context.
    }
} catch (e) {
    console.log(e.message);
}

.trim()안쪽에 추가 getStringsFromChildren()하여 선행 및 후행 공백을 제거 할 수 있습니다 (또는 공백을 길이가 0 인 문자열 ( "") 로 변환 할 수 있지만 모든 응용 프로그램이 텍스트 (문자열)에 발생해야하는 일을 사전에 알 수있는 방법). 일단 발견되면 발견하지 못하므로 특정 구현에 맡기고 getStringsFromChildren()일반화하십시오.

이 수준의 특이성 (the targetand such)이 필요하지 않은 경우가 있을 수 있습니다 . 그거 좋네. 이 경우 간단한 해결책을 사용하십시오. 그러나 일반화 된 알고리즘을 사용하면 간단하고 복잡한 상황을 수용 할 수 있습니다.


답변

첫 번째 #text 노드 콘텐츠를 반환하는 ES6 버전

const extract = (node) => {
  const text = [...node.childNodes].find(child => child.nodeType === Node.TEXT_NODE);
  return text && text.textContent.trim();
}


답변

.text() - for jquery

$('.title').clone()    //clone the element
.children() //select all the children
.remove()   //remove all the children
.end()  //again go back to selected element
.text();    //get the text of element