Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use querySelectorAll on an array of elements?

Say I have an array of DOM elements based on any selector

var elems = document.querySelectorAll(selector);

I have no idea what's included in elems, but let's assume that elems.length > 0

I'd like to use querySelectorAll (or some equivalent function) on elems to find all elements that match an additional selector.

// example: find all buttons with class `foo` within `elems` array
var buttons = elems.querySelectorAll("button.foo");

This doesn't work (for obvious reasons), but I'm unsure of how to do it otherwise :(


Here's the wrapper I created to work with the accepted answer from @Tibos

// Element.matches wrapper
(function(e){
  if (typeof e.matches !== "function") {
    e.matches = e.webkitMatchesSelector ||
                e.mozMatchesSelector    ||
                e.msMatchesSelector     ||
                e.oMatchesSelector      ||
                e.matchesSelector;
  }
})(Element.prototype);
like image 898
Mulan Avatar asked Feb 18 '14 18:02

Mulan


People also ask

Does document querySelectorAll return array?

The querySelectorAll method returns an array-like object called a node list. These data structures are referred to as “Array-like”, because they appear as an array, but can not be used with array methods like map and forEach .

How do you turn querySelectorAll into an array?

You can convert it to an array by using the slice method from the Array prototype: var elList = document. querySelectorAll('. viewcount'); elList = Array.

Can you use querySelector on an element?

The querySelector() method is available on the document object or any Element object.

Can you select multiple elements with querySelector?

Instead of the standard querySelector method, we use the querySelectorAll method. This way we can select multiple elements and store them in an array.


3 Answers

You can use the Element#matches method to filter out your original list:

var elems = document.querySelectorAll(selector);
var buttons = Array.prototype.filter.call(elems, function(elem){ 
  return elem.matches('button');
});

Note that there are various names under which you find this method, you might want to wrap a function around them. (Please check the documentation!)

Another possibility is to get the intersection of the two sets of elements returned by document.querySelectorAll with the two selectors. There are various implementations of the intersection of two sets, feel free to use one that is to your liking. This question provides some ideas.

like image 55
Tibos Avatar answered Sep 25 '22 16:09

Tibos


Here is my take as long as matches isn't more standard.

function getElementsFromParents(parentSelector, childSelector) {
    var elems = document.body.querySelectorAll(parentSelector);
    return Array.prototype.reduce.call(elems, function matcher(arr, el) {
        var matches = el.querySelectorAll(childSelector);
        if (matches.length) Array.prototype.forEach.call(matches, function pusher(item) {
            arr.push(item);
        });
        return arr;
    }, []);
}
like image 23
Olli K Avatar answered Sep 26 '22 16:09

Olli K


querySelectorAll returns a NodeList structure, so we change for an array list and we can use the function map.

  var lines = Array.prototype.slice.call(document.querySelectorAll(selector));
  var paths = lines.map(function(elem){ 
    return elem.querySelector('button');
  });
like image 34
Davin anaya Avatar answered Sep 25 '22 16:09

Davin anaya