Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

removing all text nodes from a particular div tag using javascript

i have some dynamically generated html from a php script. the php code looks like this

echo "<div id='categories'>\n";
foreach($category as $k => $v)
{
echo "<div class='category'>\n";
echo "<div id=\"$k\" class='cat_name'\n>$k</div>\n";
echo "<div id=\"$k".'_link"'." class='cat_link'>\n<a href=$v>Link</a>\n</div>\n";
echo "</div>\n";
}
echo "</div>\n";

i have a javascript file that tries to access the dom like this

var categories=document.getElementById('categories').childNodes;
for(i=0;i<categories.length;i++)
{
var link=categories[i].childNodes[1].childNodes[0].attributes['href'];
..
...
..

now this doesnt work as expected because there are text nodes in the html. when i used the firebug console to try this

document.getElementById('categories').childNodes[0].nodeType; // displays 3 

it displays 3 which means that the node is a text node. i tried adding document.normalize(); in window.onload like this

window.onload=function() {
document.normalize();
var categories=document.getElementById('categories').childNodes;
...
...

but the text nodes remain in the html. how can i remove all the text nodes. now i dont think there is any method like getElementByType() so how do i get all text nodes.

like image 558
lovesh Avatar asked Feb 24 '23 18:02

lovesh


2 Answers

Use .children instead of .childNodes to target elements only (no text nodes):

   // --------------------------------------------------v
var categories=document.getElementById('categories').children;

FF3 doesn't support that property, so if you're supporting that browser, you'll need a method to replicate it.

function children( parent ) {
    var node = parent.firstChild;
    var result = [];
    if( node ) {
        do {
            if( node.nodeType === 1 ) {
                result.push( node );
            }
        } while( node = node.nextSibling )
    }
    return result;
}
var parent = document.getElementById('categories');
var categories= parent.children || children( parent );

Also note that IE will give you comment nodes as well, so it would be better if your markup didn't include comments.

like image 124
user113716 Avatar answered Feb 26 '23 07:02

user113716


EE2015 syntax:

var elm = document.querySelector('ul');

console.log(elm.outerHTML);

// remove all text nodes
[...this.elm.childNodes].forEach(elm => elm.nodeType != 1 && elm.parentNode.removeChild(elm))

console.log(elm.outerHTML);
<ul>
  <li>1</li>
  a
  <li>2</li>
  b
  <li>3</li>
</ul>

Breakdown:

  1. Get all children
  2. Convert the HTMLCollection to an Array
  3. Traversing the Array and checking each item if it's of type text node
  4. If so, remove the item from the DOM

This will only remove direct-child text nodes and nothing deeper in the tree.


with NodeIterator:

var elm = document.querySelector('ul')

// print HTML BEFORE removing text nodes
console.log(elm.outerHTML)

// remove all text nodes
var iter = document.createNodeIterator(elm, NodeFilter.SHOW_TEXT)
var node;
while (node = iter.nextNode()) {
    node.parentNode.removeChild(node)
}

// print HTML AFTER removing text nodes
console.log(elm.outerHTML)
<ul>
  <li>1</li>
  <li>2</li>
  <li>3<span>4</span></li>
</ul>
like image 43
vsync Avatar answered Feb 26 '23 09:02

vsync