6

What I mean is how does JavaScript store DOM elements when you do something like:

var foo = document.getElementsByTagName('p');

what does foo become? an array of objects? and how can I add more elements to that variable, for example:

var bar = document.form[0].getElementsByTagName('input'); // 5 elements
var foo = document.form[1].getElementsByTagName('input'); // 4 elements

bar =+ foo;

for (i=0;i<bar.length;i++){
console.log(bar.value); // 9 logged values
}

Is it possible to add more elements of the same type to a variable that already has elements in it? Do I have to loop trough all elements in the variable I want to add and "push" them in the variable I want all the data in?

Samuel Lopez
  • 2,360
  • 6
  • 29
  • 39
  • use getElementsByTagName() instead of getElementsByName() – Givi Jun 19 '13 at 21:40
  • What would be the difference between using TagName and Name? – Samuel Lopez Jun 19 '13 at 21:44
  • 1
    The getElementsByTagName() method accesses all elements with the specified tagname, and getElementsByName() method accesses all elements with the specified name. tagname is html element tag name such as
    or

    and name is attribute such as

    – Givi Jun 19 '13 at 21:46

3 Answers3

9

getElementsByTagName (and similar methods such as getElementsByName, getElementsByClassName, etc) returns a NodeList (or HTMLCollection, depending on the browser apparently, see also Difference between HTMLCollection, NodeLists, and arrays of objects).

Even though it is an array-like object, i.e. it has numeric properties and a .length property, you cannot add new elements to it.

In order to modify the NodeList, you have to convert it to a regular array. This can easily be achieved with the array method .slice and at the same time you can merge both lists with .concat:

bar = Array.prototype.slice.call(bar).concat(Array.prototype.slice(foo));

This works because most native array methods are defined in such a way that the argument does not have to be an actually array, but an array-like object.

The noteworthy differences between a NodeList and the final array are:

  • The array is not live anymore, i.e. the collection is not automatically updated when new DOM nodes are added.
  • The elements in the final (merged) array won't necessarily be in document order.
Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Thanks for the wonderful answer, the example, the links for further reference and answering all my questions! – Samuel Lopez Jun 20 '13 at 13:20
  • Hi Felix I thought that you could may be help me with a question that I haven't got any answers only low views. I would greatly apreciate it! [Difference between contentDocument and contentWindow](http://stackoverflow.com/questions/17197084/difference-between-contentdocument-and-contentwindow-javascript-iframe-frame-acc) – Samuel Lopez Jun 25 '13 at 16:51
  • Note that for IE<9 `Array.prototype.slice.call(bar)` does not work it will output the error: "JScript Object Expected" for a workaround loop through all elements in each NodeList and add them to an array a complete example can be found in [[function].apply() causing “JScript object expected” error in IE](http://stackoverflow.com/q/11112950/1079232) – Samuel Lopez Aug 02 '13 at 14:18
  • @SamuelLopez: Try to pass `0` as second argument: `Array.prototype.slice.call(bar, 0)`. – Felix Kling Aug 02 '13 at 14:19
  • So IE supports the method but it expects 2 arguments? I found the question above while searching for information on the error and found that example. – Samuel Lopez Aug 02 '13 at 14:22
  • @Samuel: Well, `.slice` usually takes an argument to define the position where the slicing should start. If that value is `undefined` (e.g. when you don't pass an argument) it usually gets converted to `0`. But maybe IE does another check whether an argument is passed or not. – Felix Kling Aug 02 '13 at 14:33
  • I tried it as you said, `Array.prototype.slice.call(bar, 0)` but the same error was thrown, for now I'll use the loop since we need to use this small script on IE 8, if you have any more suggestions I'll gladly try them thanks! – Samuel Lopez Aug 02 '13 at 14:58
1

bar =+ foo;

this works only for string concatenation and it would be bar+= foo

but both bar and foo here are DOM objects. so if you want to add elements of the same type u can create an array.

e.g.,

var myArray =[]
myArray.push(foo);
myArray.push(bar);
Gokul Kav
  • 839
  • 1
  • 8
  • 14
  • Your example would create an array with two values, both of them would be `NodeLists`, not elements. It would not merge both `NodeList`s – Felix Kling Jun 19 '13 at 21:59
  • well he mentioned he wanted to add elements to a variable which already had elements to it – Gokul Kav Jun 19 '13 at 23:30
-4

foo becomes the function. So you wouldn't be able to add foo to bar because that doesn't make sense. It would be like trying to do:

document.form[0].getElementsByName('input') document.form[1].getElementsByName('input');

You could have multiple elements in a single array. I'd find that to be the simplest way to reach your solution.

VinylScratch
  • 123
  • 9
  • 5
    foo becomes node list not function – Givi Jun 19 '13 at 21:42
  • ooo I get it now, is there any way then to store elements in a variable so later you can add more elements to the variable? would using TagName change something like @Givi said? – Samuel Lopez Jun 19 '13 at 21:45
  • @SamuelLopez Felix Kling provided the perfect answer to your question – Givi Jun 19 '13 at 21:49
  • @Givi yes he did I just got involved with another task and didn't have time to select it as the response :s I did upvote it though and it is perfect! – Samuel Lopez Jun 20 '13 at 13:18