Maksim Nesterenko
Maksim Nesterenko

Reputation: 6213

Javascript splice for array of DOM elements

var myArray = [];
myArray = document.querySelectorAll('.selected');

And when I called myArray.splice - it was undefined. How can I avoid this? I need remove some of DOM elements from that array.

Upvotes: 5

Views: 3420

Answers (3)

Alexander Art
Alexander Art

Reputation: 1589

document.querySelectorAll returns a NodeList, not an Array.

Hence there is no Splice method on NodeList By default.

However you can prototype similar method for A node list.

Here is a working JSFiddle, it removes elements like splice directly from DOM, you can modify it however you wish.

var myArray = [];
myArray = document.querySelectorAll('.selected');

//This is a primitive analogue of splice without adding new elements, it will not remove element from NodeList, however will remove it directly from dome, then it will return the resulting array (As Array), because NodeList is unmodifiable;
NodeList.prototype.splice = function(pos, numToRemove){
    var initRemCount = remCount = numToRemove ? numToRemove : 1;
    var removed = [];
    for(var i = 0; i < this.length; i++){
        if(!remCount)
            break;
        var elm = this[i];
        if(i >= pos){
            //elm.parentElement.removeChild(elm); //I commented this out, 'cause you say you dont want to delete members from DOM, uncomment this to do so
            remCount--;
        }
    }
    return [].slice.call(this, pos, pos + initRemCount); 
}

var resultArray = myArray.splice(2, 2);

//This is the Araay already not a NodeList
console.log(resultArray);

Upvotes: 1

UltraInstinct
UltraInstinct

Reputation: 44444

The problem is that querySelectorAll(..) returns a list of nodes (NodeList) -- not a standard JS array.

May be you'd want something like below:

Array.prototype.slice.call(document.querySelectorAll('.selected'),  <begin>, <end>);

UPDATE

I missed the portion where you are trying to delete, thanks @torazaburo. Fortunately, you can directly apply filter on the NodeList instead of going via an array conversion. Something like below:

var arrayOfNodes = [].filter.call(document.querySelectorAll(".selected"), function(curNodeItem) {
     return shouldCurrentNodeBeRetained(curNodeItem)? true : false;
    //expanded for clarity.    
});

Upvotes: 7

dfsq
dfsq

Reputation: 193261

querySelectorAll is a NodeList array-like collection, but it's not an array, since it doesn't inherit from Array.prototype. To convert it to real array you would use slice this way:

var myArray = [].slice.call(document.querySelectorAll('.selected'));

It is possible to use slice like this due to the fact that Array.prototype.slice is intentionally generic method, meaning that it's internal implementation doesn't check if this value is actually Array instance. So slice can be used with any array-like objects, having numeric indexes and length property.

Upvotes: 6

Related Questions