Concatenating html object arrays with javascript

10.4k Views Asked by At

I'm attempting to merge two arrays made up of html objects. For some reason using .concat() will not work for me.

Here's a simple pen to demonstrate the problem: http://codepen.io/anon/pen/kIeyB

Note: I tried searching for something remotely similar but found nothing that answered my question.

I figure you can do this the ole fashion way using for-loops but I rather not re-invent the wheel.

var x = document.getElementById("hello");
var items = x.getElementsByClassName("one");
//alert(items.length);
var items2 = x.getElementsByClassName("two");
//alert(items2.length);
items = items.concat(items2);
//alert(items.length);
4

There are 4 best solutions below

3
On BEST ANSWER

items and items2 are nodeList or HTMLCollection objects, not arrays. They do not contain a .concat() method. They have a .length property and support [x] indexing, but they do not have the other array methods.

A common workaround to copy them into an actual array is as follows:

// convert both to arrays so they have the full complement of Array methods
var array1 = Array.prototype.slice.call(x.getElementsByClassName("one"), 0);
var array2 = Array.prototype.slice.call(x.getElementsByClassName("two"), 0);
0
On

document.getElementsByClassName doesn't return an array. It returns NodeList which has length property.

1
On

What you have are HTMLCollections, which although behave like arrays, but are not arrays. See here: https://developer.mozilla.org/en/docs/Web/API/HTMLCollection:

..A collection is an object that represents a lists of DOM nodes..

In your case, you could concatenate these objects together into a new array:

var itemsnew;
var x = document.getElementById("hello");
var items = x.getElementsByClassName("one");
var items2 = x.getElementsByClassName("two");
itemsnew = Array.prototype.concat.call(items, items2);

Now, if you:

console.log(itemsnew);

Will return:

[HTMLCollection[1], HTMLCollection[1]]

And:

console.log(itemsnew[0][0]);

Will return:

<div class="one"></div>
0
On

This can be also be done like this:

var allitems = [];
allitems = Array.prototype.concat.apply(allitems, x.getElementsByClassName("one"));
allitems = Array.prototype.concat.apply(allitems, x.getElementsByClassName("two"));

The allitems variable will be a single javascript Array containing all elements with class one & two.