Is there a way to get innerText of only the top element (and ignore the child element's innerText)?

18,082

Solution 1

Just iterate over the child nodes and concatenate text nodes:

var el = document.getElementById("your_element_id"),
    child = el.firstChild,
    texts = [];

while (child) {
    if (child.nodeType == 3) {
        texts.push(child.data);
    }
    child = child.nextSibling;
}

var text = texts.join("");

Solution 2

This will work in your example: document.getElementById("item").firstChild.nodeValue;

Note: Keep in mind that this will work if you know you are dealing with that specific HTML. If your HTML can change, for example to:

<div> 
    <div class="item"> child node text </div>
    top node text 
</div>

then you should use the more generic solution by @Tim Down


Here is working code snippet:

window.onload = function() {
   var text = document.getElementById("item").firstChild.nodeValue;
   document.getElementById("result").innerText = text.trim();
};
#result {
  border: 1px solid red;
}
<div id="item">
  top node text 
   <div> child node text </div>
</div>



<strong>Result:</strong> <div id="result"></div>

Solution 3

  1. Clone the element.
  2. Loop through all child nodes (backwards, to avoid conflicts):
    If the element has a tagName attribute, then it's an element: Remove the node.
  3. Use innerText to get the textual contents (with fallback to textContent, when innerText is not supported).

Code:

var elem = document.getElementById('theelement');
elem = elem.cloneNode(true);
for (var i=elem.childNodes.length-1; i>=0; i--) {
    if (elem.childNodes[i].tagName) elem.removeChild(elem.childNodes[i]);
}
var innerText = elem['innerText' in elem ? 'innerText' : 'textContent'];

Solution 4

function getDirectInnerText(element) {
  var childNodes = element.childNodes;
  result = '';

  for (var i = 0; i < childNodes.length; i++) {
    if(childNodes[i].nodeType == 3) {
      result += childNodes[i].data;
    }
  }

  return result;
}

element = document.querySelector("div#element");
console.log(getDirectInnerText(element))
<div id="element"> 
   top node text 
   <div> child node text </div>
</div>
Share:
18,082

Related videos on Youtube

ivymike
Author by

ivymike

Updated on June 04, 2022

Comments

  • ivymike
    ivymike over 1 year

    Is there a way to get innerText of only the top element (and ignore the child element's innerText) ?

    Example:

    <div> 
       top node text 
       <div> child node text </div>
    </div>
    

    How to get the "top node text" while ignoring "child node text" ? innerText property of top div seem to return concatenation of both inner , top text.

    • Oded
      Oded over 11 years
      Remove the non text direct child nodes first?
    • Tim Down
      Tim Down over 11 years
      @Oded: No need. Just iterate over the children and concatenate. Easy peasy.
  • ivymike
    ivymike over 11 years
    Wow, works like charm in all browsers. Frankly, I didn't think it was possible before posting the question :) ... thank you...
  • Tim Down
    Tim Down over 11 years
    No need to clone or mutate the DOM at all. Just read the text node children. See my answer.
  • Daniel Earwicker
    Daniel Earwicker over 11 years
    +1 Clearly better than cloning what may be a very large bit of DOM tree, just to discard most of it. Only improvement would be text = [] at the start, and then text.push(child.data) per iteration, and finally text = text.join('') at the end to turn the array of pieces into a string, which tends to be faster than repeated concatenations to an ever-growing string.
  • Tim Down
    Tim Down over 11 years
    @DanielEarwicker: I considered that, but I think the last benchmarks I saw suggested it was not clear cut that it actually improves performance so I went for the simpler version. I'll check now.
  • Rob W
    Rob W over 11 years
    Nice one. PS. data is the defined in the CharacterData interface, which is implemented by Text (text nodes).
  • Rob W
    Rob W over 11 years
    @ivymike Tims's method is better. I suggest to accept his answer instead of mine. It also works in all browsers (tested in IE6+, Chrome 1+, Safari 5, Firefox 3+).
  • Tim Down
    Tim Down over 11 years
    @DanielEarwicker: Seems as though array join may well be slower in modern browsers but is way quicker in IE 7, which trumps everything since your slowest target browser is where you actually need performance gains. Amending...
  • William Ardila
    William Ardila over 6 years
    Instead 3 you can use Node.TEXT_NODE Source (See named constants)
  • Tim Down
    Tim Down over 6 years
    @WilliamArdila: True. It was true in 2012 except for IE <= 8, which hadn't gone away by that point.
  • Tom
    Tom about 6 years
    Am I missing something, or is this the opposite of what they're asking for?