How can I convert an Array of nodes to a static NodeList?

why can’t I use the NodeList constructor to create a NodeList

Because the DOM specification for the NodeList interface does not specify the WebIDL [Constructor] attribute, so it cannot be created directly in user scripts.

why can’t I cast an array to a NodeList in a similar fashion that NodeLists are cast to arrays?

This would certainly be a helpful function to have in your case, but no such function is specified to exist in the DOM specification. Thus, it is not possible to directly populate a NodeList from an array of Nodes.

While I seriously doubt you would call this “the right way” to go about things, one ugly solution is find CSS selectors that uniquely select your desired elements, and pass all of those paths into querySelectorAll as a comma-separated selector:

// find a CSS path that uniquely selects this element
function buildIndexCSSPath(elem) {
    var parent = elem.parentNode;

     // if this is the root node, include its tag name the start of the string
    if(parent == document) { return elem.tagName; } 

    // find this element's index as a child, and recursively ascend 
    return buildIndexCSSPath(parent) + " > :nth-child(" + (Array.prototype.indexOf.call(parent.children, elem)+1) + ")";
}

function toNodeList(list) {
    // map all elements to CSS paths
    var names = list.map(function(elem) { return buildIndexCSSPath(elem); });

    // join all paths by commas
    var superSelector = names.join(",");

    // query with comma-joined mega-selector
    return document.querySelectorAll(superSelector);
}

toNodeList([elem1, elem2, ...]);

This works by finding CSS strings to uniquely select each element, where each selector is of the form html > :nth-child(x) > :nth-child(y) > :nth-child(z) .... That is, each element can be understood to exist as a child of a child of a child (etc.) all the way up the root element. By finding the index of each child in the node’s ancestor path, we can uniquely identify it.

Note that this will not preserve Text-type nodes, because querySelectorAll (and CSS paths in general) cannot select text nodes.

I have no idea if this will be sufficiently performant for your purposes, though.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)