最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

dom - Remove all child nodes but leave the text content of the node in javascript (no framework) - Stack Overflow

programmeradmin5浏览0评论

I'm trying to remove all child elements from a node but leave the actual text content of the node. I.e. go from this:

<h3>
   MY TEXT
   <a href='...'>Link</a>
   <a href='...'>Link</a>
   <select>
      <option>Value</option>
      <option>Value</option>
   </select>
</h3>

to this:

<h3>
   MY TEXT
</h3>

I know that there are a million easy ways to do this in jQuery, but it's not an option for this project... I've got to use plain old javascript.

This:

var obj = document.getElementById("myID");
if ( obj.hasChildNodes() ){
    while ( obj.childNodes){
        obj.removeChild( obj.firstChild );       
    }
}

obviously results in just <h3></h3>, and when I tried:

var h3 = content_block.getElementsByTagName('h3')[0];
var h3_children = h3.getElementsByTagName('*');
for(var i=0;i<h3_children.length;i++){
   h3_children[i].parentNode.removeChild(h3_children[i]);
}

It gets hung up part way through. I figured it was having trouble removing the options, but altering the for loop to skip removal unless h3_children[i].parentNode==h3 (i.e. only remove first-level child-elements) stops after removing the first <a> element.

I'm sure I'm missing something super obvious here, but perhaps it's time to turn to the crowd. How can I remove all child elements but leave the first-level textNodes alone? And why doesn't the above approach work?

EDITS

There are a couple of working solutions posted, which is great, but I'm still a little mystified as to why looping through and removing h3.getElementsByTagName('*') doesn't work. A similar approach(adapted from Blender) likewise does not plete the process of removing child nodes. Any thoughts as to why this would be?

I'm trying to remove all child elements from a node but leave the actual text content of the node. I.e. go from this:

<h3>
   MY TEXT
   <a href='...'>Link</a>
   <a href='...'>Link</a>
   <select>
      <option>Value</option>
      <option>Value</option>
   </select>
</h3>

to this:

<h3>
   MY TEXT
</h3>

I know that there are a million easy ways to do this in jQuery, but it's not an option for this project... I've got to use plain old javascript.

This:

var obj = document.getElementById("myID");
if ( obj.hasChildNodes() ){
    while ( obj.childNodes){
        obj.removeChild( obj.firstChild );       
    }
}

obviously results in just <h3></h3>, and when I tried:

var h3 = content_block.getElementsByTagName('h3')[0];
var h3_children = h3.getElementsByTagName('*');
for(var i=0;i<h3_children.length;i++){
   h3_children[i].parentNode.removeChild(h3_children[i]);
}

It gets hung up part way through. I figured it was having trouble removing the options, but altering the for loop to skip removal unless h3_children[i].parentNode==h3 (i.e. only remove first-level child-elements) stops after removing the first <a> element.

I'm sure I'm missing something super obvious here, but perhaps it's time to turn to the crowd. How can I remove all child elements but leave the first-level textNodes alone? And why doesn't the above approach work?

EDITS

There are a couple of working solutions posted, which is great, but I'm still a little mystified as to why looping through and removing h3.getElementsByTagName('*') doesn't work. A similar approach(adapted from Blender) likewise does not plete the process of removing child nodes. Any thoughts as to why this would be?

Share Improve this question edited May 23, 2017 at 12:12 CommunityBot 11 silver badge asked Oct 19, 2012 at 5:40 Ben DBen D 14.5k3 gold badges47 silver badges59 bronze badges 2
  • 1 Oddly, this removes all but one <a> element: jsfiddle/rSbmR – Blender Commented Oct 19, 2012 at 5:51
  • @Blender - Yeah, I was getting similar results with the getElementsByTagName loop (removal of most but not all of the elements). Any thoughts as to why? – Ben D Commented Oct 19, 2012 at 6:05
Add a ment  | 

5 Answers 5

Reset to default 3
var h3=content_block.getElementsByTagName("h3")[0];
for(var i=0;i<h3.childNodes.length;i++)
{
  if(h3.childNodes[i].nodeType==3)//TEXT_NODE
  {
    continue;
  }
  else
  {
    h3.removeChild(h3.childNodes[i]);
    i--;
  }
}

JSFiddle demo

Edit:

Combined the i-- to make it look shorter:

var h3=content_block.getElementsByTagName("h3")[0];
for(var i=0;i<h3.childNodes.length;i++)
{
  if(h3.childNodes[i].nodeType==3)//TEXT_NODE
    continue;
  else
    h3.removeChild(h3.childNodes[i--]);
}

Edit #2:

Pointed out by @SomeGuy, make it even shorter:

var h3=content_block.getElementsByTagName("h3")[0];
for(var i=0;i<h3.childNodes.length;i++)
{
  if(h3.childNodes[i].nodeType!=3)//not TEXT_NODE
    h3.removeChild(h3.childNodes[i--]);
}

The brackets can be removed too, but that would be "less readable" and "confusing", so I keep it there.

You can check properties .nodeType or .nodeName for each node.

Text nodes have these properties set to:

.nodeType == 3
.nodeName == '#text'`

For instance:

var e = obj.firstChild
while (e) {
   if (e.nodeType == 3) {
      e = e.nextSibling
   } else {
      var n = e.nextSibling
      obj.removeChild(e)
      e = n
   }
}

try this. I am assuming you will keep ant text here.

var h3 = document.getElementsByTagName('h3')[0];

if (h3.hasChildNodes()) {
    for (var i = h3.childNodes.length - 1; i >= 0; i--) {
        if (h3.childNodes[i].nodeName != "#text")
            h3.removeChild(h3.childNodes[i]);
    }
}

Hope it will work.

Well, The thing I used (inspired from the answers here) is somewhat like:

   var h3 = document.getElementsByTagName("h3")[0];
    Array.protoype.filter.call(h3.childNodes, function(child){
        if (child.nodeType != 3) {
            h3.removeChild(child);
        }
    });
发布评论

评论列表(0)

  1. 暂无评论