2

I try to merge two node list in one but when I concat in one array, there is two time the same node. Concat do not search if nodes to insert already exist in array...

var firstNodelist = document.querySelectorAll("#outter, #inner");
var finalArray = new Array();

for (var i = 0; i < firstNodelist.length; i++) {

    var secondNodelist = firstNodelist[i].querySelectorAll("div");

    var firstArray = new Array();

    for (var x = 0; x < secondNodelist.length; x++) {

        firstArray.push(secondNodelist[x]);

    }

    finalArray = finalArray.concat(firstArray)

}

console.log("FINAL", finalArray);

The jsfiddle exemple

Jordan
  • 3,776
  • 3
  • 22
  • 28

1 Answers1

3

Rather than building a second, unnecessary array within your loop, just use that inner loop to check whether the node is already in the array (Array#indexOf on all modern browsers) and only add it if it isn't.

var firstNodelist = document.querySelectorAll("#outter, #inner");
var finalArray = []; // `[]` rather than `new Array()`

for (var i = 0; i < firstNodelist.length; i++) {

    var secondNodelist = firstNodelist[i].querySelectorAll("div");

    for (var x = 0; x < secondNodelist.length; x++) {

        // Get this node
        var node = secondNodeList[x];

        // Is it in the array already?
        if (finalArray.indexOf(node) === -1) {
            // No, put it there
            finalArray.push(node);
        }

    }
}

console.log("FINAL", finalArray);

Be sure to test your target environment(s) to be sure they have Array#indexOf.


Having said that, there's a much better way for that specific situation: Live Example | Live Source

var finalArray = Array.prototype.slice.call(
    document.querySelectorAll("#outter div, #inner div")
);

...since querySelectorAll won't include the same node more than once, even if #inner is inside #outter (or vice-versa). (The Array.prototype.slice.call(someObject) is a trick to get a true array from any array-like object.)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Work fine ! Thank you ! The jsfiddle exemple : http://jsfiddle.net/3uCFV/3/ Edit: do you know why indexOf(node) work and not if( nodeList[i] = node ) ???? – Jordan Oct 13 '13 at 15:10
  • @Jordan: `indexOf` searches the entire array for a match. I don't know what your second bit of code in that comment is meant to be, as there's no `nodeList` symbol in your question or my answer. Do be sure to check out the second part of the answer, btw. – T.J. Crowder Oct 13 '13 at 15:13
  • Array.prototype.slice.call() transform nodeList to array but if I already have a variable (array of node) and then I try to got "div" from these nodes, I need to do a "for" loop. So I need to create a new empty array and push node if not already exist. – Jordan Oct 13 '13 at 15:28
  • for the if( nodeList[i] === node ){ ... } I mean, if I try to compare two node like that, he respond me false everytime. So why indexOf work ? – Jordan Oct 13 '13 at 15:30
  • @Jordan: If you have a `nodeList` and the entry at position `i` is the same element you have referenced in `node`, that statement **will** be true. Proof (on a page with an element with the `id` `"something"`: `console.log(document.getElementById("something") === document.querySelectorAll("#something")[0])` will log `true`. If you weren't seeing that, then `nodeList[i]` referred to a different node than `node`. – T.J. Crowder Oct 13 '13 at 15:45
  • I surely do something bad, cause you say that and that is working too : http://stackoverflow.com/questions/2234979/how-to-check-in-javascript-if-one-element-is-a-child-of-another – Jordan Oct 13 '13 at 17:41