Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appending elements to DOM in a loop structure

Tags:

javascript

dom

Once the page has been loaded, I would like to append an additional element for each existing elements on the page.

I tried something like this:

    var divs=document.getElementsByTagName('div');

    for(i=0;i<divs.length;i++){
        newDiv=document.createElement('div');
        divs[i].appendChild(newDiv);
    }

Just a warning this will actually freezes the browser because the divs variable is dynamic and divs.length just gets larger and larger each time the loop goes.

Is there a way to determine the number of tags when the DOM is normally loaded for the first time and have a chance to work with the elements statically.

I can't there of another solution so far.

Thanks so much. Dennis!

like image 765
Dennis D Avatar asked Jul 07 '10 20:07

Dennis D


People also ask

Can appendChild take multiple arguments?

append() method supports multiple arguments and appending strings. You can prefer using it if your node is an element.

How do you iterate over elements in HTML?

To iterate over the selected elements, you can use forEach() method (supported by most modern web browsers, not IE) or just use the plain old for-loop.


1 Answers

The problem is that DOM collections are live, and when the underlying document structure is changed, it will be reflected automatically on the collection, that's why when the length property is accessed it will contain a new length, a common approach is to cache the length before starting the loop:

var divs=document.getElementsByTagName('div');

for(var i = 0, len = divs.length;i<len;i++){
    var newDiv = document.createElement('div');
    divs[i].appendChild(newDiv);
}

Also notice that you should declare all your variables with the var statement, otherwise it might become global.

Edit: In this case, since you are appending child nodes of the same tagName, the collection will be modified, and the indexes will no longer match, after the first iteration, the index 1 will refer to the newDiv object from the previous iteration, as @Casey recommends it will be safer to convert the collection to a plain array before traversing it.

I use the following function:

function toArray(obj) {
  var array = [];
  // iterate backwards ensuring that length is an UInt32
  for (var i = obj.length >>> 0; i--;) { 
    array[i] = obj[i];
  }
  return array;
}

//...
var divs = toArray(document.getElementsByTagName('div'));
//...
like image 198
Christian C. Salvadó Avatar answered Oct 20 '22 08:10

Christian C. Salvadó