Javascript - Concatenate Multiple NodeLists Together
Asked Answered
S

6

20

I was originally asking for an elegant way to simulate the Array.concat() functionality on the results of the getElementsByTagName function in IE or older browsers, because it seemed that concat was not supported. Only, of course it is--the reason the returned object didn't support it is because it isn't an Array. Oops!

getElementsByTagName actually returns a NodeList. The real question, then, is: what's a good way to get a single list of all the form elements in a document (input, select, textarea, button) to loop through them? An array isn't required... a single NodeList would be perfect, too.

Note that I'm using IE6 as this is for a corporate intranet (soon IE8 though).

The answer that I came up with was:

  • It became simpler and probably performed better to just put the code into a separate function and call it three times with the different nodelists, rather than worry about a good way to cram them together into one.

  • I ultimately switched to using MooTools (after several hours reading up on comparisons of all the different frameworks). So now, getting an array of the items I want is very simple. I recommend using a javascript framework like this rather than people beating their brains out trying to figure out the best way to do things. Of course I'm all for actually learning the raw language (which is why I've held off using a framework for so long) but it isn't always the fastest way to get things going, which in a business often matters as much as improving the coder's ability with the language.

Update: almost 2 years later I would just use jQuery and be done with it!

Shopwindow answered 12/3, 2010 at 2:29 Comment(3)
IE supports this, can you clarify the question a bit?Brahe
Using jQuery is definitely the way to go. I came across this in a case where I didn't have access to jQuery, though. I ended up creating an array of element tags I wanted to act on and looping through it, calling getElementsByTagName for each one. I wonder if that's more or less efficient than the top answer.Hax
@Hax But did you put all the elements into a single array at any point, or just work with them one tag's worth at a time?Shopwindow
L
31

To concatenate nodelists, convert them into arrays using Array.prototype.slice.call and then concat them normally.

var a = Array.prototype.slice.call(document.getElementsByTagName("p")),
    b = Array.prototype.slice.call(document.getElementsByTagName("div"))

var c = a.concat(b);

Edit: (Responding to your comment)

If you only have a few types of elements, this is okay but the performance decreases with the number of DOM calls you make. It may be better and faster to do a document.getElementsByTagName('*'), loop thru the list and pick the elements with the required nodeName.

Another thing to keep in mind is that the Array.prototype.slice method used above may not work in ALL browsers. Check out the comment starting line#723 in sizzle.js (the selector engine behind jQuery)

Of course, it is best to use a library like jQuery which handles all the headache. You can simply do:

$("input, select, textarea, <other tags>")
Liatris answered 12/3, 2010 at 2:59 Comment(3)
I was just looking for a simple way to get a list of multiple elements (in this case, form elements INPUT, SELECT, TEXTAREA, and possibly BUTTON). Is this the best way? I guess it's time to open a new question.Shopwindow
Quotation is needed for the document.getElementsByTagName("*") call, and nodeName is the thing to look for.Councilor
Keep in mind that this turns the nodelist into an array, which may not have the methods available that you require, such as nodeName.valueTemporary
L
9

With the ES6 spread operator you can do

let arr = [...nodeList1, ...nodeList2];
Liv answered 12/4, 2017 at 15:23 Comment(1)
I was just thinking about this yesterday!Shopwindow
P
3
function mergeNodeLists(a, b) {
  var slice = Array.prototype.slice;
  return slice.call(a).concat(slice.call(b));
}

console.log( mergeNodeLists( inputs, selects ) ); // => [input, select]

Pocketknife answered 23/6, 2013 at 15:59 Comment(1)
I don't really see that this adds much more to the selected answer. Thank you for participating, though!Shopwindow
L
2

As noted in the MDN Documentation, you can also use Array.from to convert a NodeList in to an Array on browsers that support it.

Lunik answered 11/1, 2018 at 23:7 Comment(0)
R
1
var a1=document.getElementsByTagName('div'),
a2=document.getElementsByTagName('button');
a1=[].slice.call(a1, 0,a1.length).concat([].slice.call(a2, 0,a2.length))
Roti answered 12/3, 2010 at 4:26 Comment(0)
T
0

I'd of thought there would have been more answers than this, anyway I gave this a shot and came up with the following function although I had to bang my head a little.

function group_elements(element, tags) {
   var elements = element.getElementsByTagName('*');
   var results  = [];
   for ( var i = 0; i < elements.length; ++i ) {
      if ( tags.indexOf(elements[i].nodeName.toLowerCase()) > -1 ) {
         results.push(elements[i]);
      }
   }
   return results;
}


var form  = document.getElementById('form');
var tags = ['input', 'select'];
console.log(group_elements(form, tags));
Transept answered 27/3, 2016 at 10:37 Comment(1)
Problems: don't use a string, use an array: var nodes = ['input', 'select']; then no need to split. Don't modify parameters. Redeclaring parameters is nonsensical. node is not a good name, trytagName (they're strings, not node objects). JavaScript idiomatically uses camelCase, so selected_elements should be selectedElements.Shopwindow

© 2022 - 2024 — McMap. All rights reserved.