Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to concatenate two NodeList objects into one, avoiding duplicates

Tags:

javascript

I am writing a few functions to simplify my interaction with Javascript Nodes, here is the source-code so far:

Node.prototype.getClasses = function() {
    return this.className ? this.className.split(" ") : "";
};

Node.prototype.hasClass = function(c) {
    return this.getClasses().indexOf(c) >= 0;
};

Node.prototype.addClass = function(c) {
    if (!this.hasClass(c)) {
        this.className += " " + c;
    }
    return this;
};

Node.prototype.removeClass = function(c) {
    if (this.hasClass(c)) {
        var classes = this.getClasses();
        var newClasses = [];
        for (var index = 0; index < classes.length; index++) {
            if (classes[index] !== c) {
                newClasses.push(classes[index]);
            }
        }
        this.className = newClasses.join(" ");
    }
    return this;
};

function NodeCollection(nodes) {
    this.nodes = nodes;
    this.addClass = (c) => {
        for (var nodeIndex = 0; nodeIndex < this.nodes.length; nodeIndex++) {
            this.nodes[nodeIndex].addClass(c);
        }
        return this.nodes;
    };
    this.removeClass = (c) => {
        for (var nodeIndex = 0; nodeIndex < this.nodes.length; nodeIndex++) {
            this.nodes[nodeIndex].removeClass(c);
        }
        return this.nodes;
    };
    this.getHTML = () => {
        var output = "";
        for (var nodeIndex = 0; nodeIndex < this.nodes.length; nodeIndex++) {
            output += this.nodes[nodeIndex].outerHTML;
        }
        return output;
    };
    this.each = (f) => {
        for (var nodeIndex = 0; nodeIndex < this.nodes.length; nodeIndex++) {
            f(this.nodes[nodeIndex]);
        }
        return this.nodes;
    };
}

Node.prototype.query = function(s) {
    return new NodeCollection(this.querySelectorAll(s));
};

Node.prototype.siblings = function(s) {
    var rawSiblings = this.parentNode.querySelectorAll(s);
    var output = [];
    for (var siblingIndex = 0; siblingIndex < rawSiblings.length; siblingIndex++) {
        if ((rawSiblings[siblingIndex].parentNode === this.parentNode) && (rawSiblings[siblingIndex] !== this)) {
            output.push(rawSiblings[siblingIndex]);
        }
    }
    return new NodeCollection(output);
};

Everything is working great and I am quite content with these functions, I have managed to prevent a lot of headaches without the usage of Javascript frameworks (a hobby project).

Now, I would like to be able to write a query function for NodeCollection as well, however, I am not quite aware of how should I concatenate the nodes members of the NodeCollection objects, which are instances of NodeList. I would like to write something like this as a member function of NodeCollection:

this.query = (s) => {
    //create an empty NodeList
    for (var index = 0; index < this.nodes.length; index++) {
        //concat this[nodes][index] to the node list created outside the 
        //cycle avoiding possible duplicates
    }
    //return the concatenated NodeList
};

How can I achieve this?

like image 823
Lajos Arpad Avatar asked Dec 21 '17 13:12

Lajos Arpad


1 Answers

How to concatenate two NodeList objects into one, avoiding duplicates

Use isSameNode and Array.from

Array.from( nodeList1 ).forEach( function( ele, index ){
  var isDuplicate = Array.from( nodeList2 ).some( ( ele2 ) => ele.isSameNode(ele2) );
  if ( !isDuplicate )
  {  
      nodeList2[ nodeList2.length ] = ele;
  }
})

Now nodeList2 has all the nodes from nodeList1 which are not duplicates.

Demo

var nodeList1 = Array.from( document.querySelectorAll(".a") );
var nodeList2 = Array.from( document.querySelectorAll(".b") );

console.log( "original length " + nodeList1.length, nodeList2.length );

nodeList1.forEach(function(ele, index) {
  var isDuplicate = nodeList2.some( ele2 => ele.isSameNode(ele2));
  //console.log( ele, isDuplicate );
  if (!isDuplicate) {
    nodeList2.push( ele );
  }
});

console.log( "Final length " + nodeList1.length , nodeList2.length );
<div class="a b"></div>
<div class="a"></div>
<div class="b"></div>
<div class="a b"></div>
like image 61
gurvinder372 Avatar answered Oct 25 '22 17:10

gurvinder372