Reputation: 5169
is there a way to join 2 NodeLists returned by 2 calls of document.getElementsByTagName?
Say, I have the following code
var inputs = documentElement.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');
I want to loop through the results. Is it possible in one loop?
Thank you in advance!
Upvotes: 27
Views: 29416
Reputation: 213
try my way:
var allES = [];
var inputs = document.getElementsByTagName("input");
for (i = 0; i < inputs.length; i++) {
allES.push(inputs[i]);
}
// gather SELECT elements
var selects = document.getElementsByTagName("select");
for ( i=0; i < selects.length; i++){
allES.push(selects[i]);
}
Upvotes: 0
Reputation: 33408
function mergeNodeLists(a, b) {
var slice = Array.prototype.slice;
return slice.call(a).concat(slice.call(b));
}
console.log( mergeNodeLists( inputs, selects ) ); // => [input, select]
Upvotes: 2
Reputation: 2479
Array.prototype.slice.call() fails in IE 7, use this:
Object.prototype.getMyElements = function(tags){
tags = tags.split(',');
var i, j, col=[], ci=0;
for(i=0; i<tags.length; i++) {
var objs = this.getElementsByTagName(tags[i]);
for(j=0; j<objs.length; j++) col[ci++] = objs[j];
}
return col;
}
var objs = document.getMyElements('INPUT,TEXTAREA');
var objs = document.getElementById('myform').getMyElements('INPUT,TEXTAREA');
Upvotes: 0
Reputation: 7286
Nowadays I would definitely use the following:
Chrome, Firefox 3.5+, IE8+
var elements = document.querySelectorAll('a');
for (var i = 0, element; (element = elements[i]); i++) {
console.log(element);
}
IE11+, Firefox 24+, Chrome 30+ (with experiments enabled)
let elements = document.querySelectorAll('a');
for (let i = 0, element; (element = elements[i]); i++) {
console.log(element);
}
"element = elements[i]" is preferred over "elements.length" since:
"Node lists are often implemented as node iterators with a filter. This means that getting a property like length is O(n), and iterating over the list by re-checking the length will be O(n^2)."
Unlike array access, which is as far as I remember O(1).
More details:
Upvotes: 0
Reputation: 249
My short code for bookmarklets:
var e, t = d.getElementsByTagName('textarea'), u = d.getElementsByTagName('input'), i = t.length;
while(e = (i > 0) ? t[--i] : u[-i--]){ if(e.offsetHeight > 0)... }
Upvotes: 1
Reputation: 11
I threw this together. There might be a bit of overhead from doing an if and .length for every loop, but I think its minor unless the number of elements get extreme.
inputs = div.getElementsByTagName('input');
selects = div.getElementsByTagName('select');
for (i=0; i<inputs.length+selects.length; i++) {
element = (i<inputs.length ? inputs[i] : selects[i-inputs.length]);
// do whatever with element
}
Upvotes: 1
Reputation: 37978
Seems like you can use the same Array.prototype.slice.call that makes the args array-like object become an array. (See here)
var inputs = document.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');
inputs = Array.prototype.slice.call(inputs);
selects = Array.prototype.slice.call(selects);
var res = inputs.concat(selects);
alert(res.length);
Upvotes: 45
Reputation: 5902
You can't join them, but you can still loop through them sequentially in one loop like this:
for ( var i = 0; i < inputs.length + selects.length; i++ ) {
var element = ( i < inputs.length ) ? inputs[i] : selects[i-inputs.length];
}
Alternatively, using jQuery, you could select them all in one go:
$('input, select')
Upvotes: 20
Reputation: 231
First, I thought that this is possible to concat arrays using Array.prototype, like this:
Array.prototype.concat.call(selects, inputs);
But it doesn't work, so that I've made an arrays from node collections and concat it. Looks like that:
(function () {
var inputs = document.getElementsByTagName('input'),
selects = document.getElementsByTagName('select'),
result,
i,
node;
function convert (collection) {
var a = [];
for (var i = 0, length = collection.length; i < length; i++) {
a.push(collection[i]);
}
return a;
}
// concatenation && convertation
result = Array.prototype.concat(convert(inputs), convert(selects));
// traversing
i = result.length;
while(node = result[--i]) {
alert(node.getAttribute('name'));
}
})();
Upvotes: 0
Reputation: 147340
As far as I know, the NodeList
type is immutable (see this article for example), which means you'll have to generate your own object.
A simple method would just be to create an array and copy all the elements into that array.
var inputs = documentElement.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');
var all = new Array(inputs.length + selects.length);
var index = 0;
for (i = 0; i < inputs.length; i++)
all[index++] = inputs[i];
for (i = 0; i < selects.length; i++)
all[index++] = selects[i];
The all
variable then contains the union of the two sets of nodes.
Upvotes: 4