Skip to content
Advertisement

Add array of elements to dom

I have 5 div's created in HTML, and I want to add all of them into a div wrapper I created in JavaScript. I tried looping through the 5 div's via a for-in loop, then append the div as a child of the wrapper.

For some reason, the for loop changes the 5 div's order and doesn’t append all of them in wrapper. How can I add all div's to wrapper, keeping the (HTML) order, using JavaScript?

(Please don’t post JQuery answers because that isn’t the question. I want JavaScript answers only.)

JSFiddle

var wrapper = document.createElement('div'),
  myClass = document.getElementsByClassName('myClass');

myClass[0].parentElement.appendChild(wrapper);
wrapper.id = 'wrapper';

for (var key in myClass) {
  if (!myClass.hasOwnProperty(key)) continue;

  wrapper.appendChild(myClass[key]);
}
#wrapper {
  border: 2px solid green;
  color: brown;
}
<div class="myClass">First</div>
<div class="myClass">Second</div>
<div class="myClass">Third</div>
<div class="myClass">Fourth</div>
<div class="myClass">Fifth</div>

Advertisement

Answer

The document.getElementsByClassName method returns an HTMLCollection-object, which is similar to an array, as in it has numeric keys which should be used.

e.g. for (var i = 0; i < myClass.length; ++i)

Once you use an incremental numeric index, you’ll notice it actually behaves the same as your key in myClass, which is rather logical, as the key is the numeric index.

What is happening is that an HTMLCollection represents elements in document order (a so called live list, which reflects the changes in the DOM) and you are moving them around by appending them to the wrapper element (hence the order within the HTMLCollection changes too).

There are several tricks to work around this, the one closest to your current setup would be to walk through the HTMLCollection from end to start and insertBefore instead of appendChild

for (var len = myClass.length - 1; len >=0; --len) {
    wrapper.insertBefore(myClass[len], wrapper.firstChild);
}

insertBefore fiddle

This works because the wrapper is (in your example) after the elements you’re moving into it, therefor not changing the order of the elements.

There is another (easier) approach: document.querySelectorAll. The querySelectorAll method returns a (static) NodeList, so you can safely assume the order will not change while you move nodes around.

The syntax is (IMHO) more convenient than getElementsByClassname, as it uses CSS Selectors (much like the popular javascript framework we won’t mention)

querySelectorAll fiddle

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement