For example, in jQuery, if i want all <div>
and <p>
elements, I do this:
var $x = $("p, div");
And then if i want all the <div>
elements in x, then I do this:
var $divs = $x.filter("div");
So how do i do this simple filter
thing in vanilla JavaScript?
For example, to select all <div>
and <p>
, then I can do this:
var x = document.querySelectorAll("div, p");
But vanilla JavaScript doesn't have the filter function like in jQuery, so I can't do this:
var divs = x.filter("div"); // ERROR
Hope someone can help me with this :-)
Thanks in advance.
UPDATE
Some ments/answers have suggested to do something like .tagName == "DIV" to find the divs, however, i want a solution with a string selector like in jQuery.
The reason is because i also want to filter with attributes, classes and even multiple selectors where you put in ma. And the string selector must be dynamic.
That means, i dont know whats in the selector. It could be "div[foo='asd'], .bar" or "#hello, [xx='yy'], p"
So i cant just hardcode the .tagName == "DIV", beacuse i dont know whats in the selector string.
For example, in jQuery, if i want all <div>
and <p>
elements, I do this:
var $x = $("p, div");
And then if i want all the <div>
elements in x, then I do this:
var $divs = $x.filter("div");
So how do i do this simple filter
thing in vanilla JavaScript?
For example, to select all <div>
and <p>
, then I can do this:
var x = document.querySelectorAll("div, p");
But vanilla JavaScript doesn't have the filter function like in jQuery, so I can't do this:
var divs = x.filter("div"); // ERROR
Hope someone can help me with this :-)
Thanks in advance.
UPDATE
Some ments/answers have suggested to do something like .tagName == "DIV" to find the divs, however, i want a solution with a string selector like in jQuery.
The reason is because i also want to filter with attributes, classes and even multiple selectors where you put in ma. And the string selector must be dynamic.
That means, i dont know whats in the selector. It could be "div[foo='asd'], .bar" or "#hello, [xx='yy'], p"
So i cant just hardcode the .tagName == "DIV", beacuse i dont know whats in the selector string.
Share Improve this question edited May 29, 2018 at 20:41 Assassinbeast asked May 29, 2018 at 20:15 AssassinbeastAssassinbeast 1,2772 gold badges18 silver badges35 bronze badges 9-
I am not 100% sure but I think you can just do
[anyDomElement].GetElementsByTagName("div")
– Marie Commented May 29, 2018 at 20:17 -
2
Have you opened the jQuery core code and taken a look at the
.filter()
method? – Roko C. Buljan Commented May 29, 2018 at 20:18 - Why not just write a wrapper that looks like the first code snippet but actually does the second? – Jonas Wilms Commented May 29, 2018 at 20:22
- 1 there is no such thing as "native" JavaScript ...it is monly referred to as "vanilla" or ECMA6 script. – Martin Zeitler Commented May 29, 2018 at 20:38
- 1 @MartinZeitler so you mean ECMAScript ;) – Roko C. Buljan Commented May 29, 2018 at 20:47
5 Answers
Reset to default 5You can use the matches
function to check if a CSS selector matches a given element.
var x = document.querySelectorAll("div, p");
var divs = [];
// Iterate through the elements that the first query selector matched
// (is a paragraph or a div tag)
for (var elem of x) {
// Check if the given element matches the second query selector
// (is a div tag)
if (elem.matches('div')) {
divs.push(elem);
}
}
This code can be written more succinctly (and with more modern code) using:
let x = document.querySelectorAll("div, p");
let divs = Array.from(x).filter(elem => elem.matches("div"));
you can use Array.filter
const elems = document.querySelectorAll('p, div');
const divs = [...elems].filter(e => {
return e.tagName == 'DIV'
});
console.log(divs)
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<p id="p1"></p>
<p id="p2"></p>
<p id="p3"></p>
you can change e.tagName
to filter with something else :
const elems = document.querySelectorAll('p, div');
const divs = [...elems].filter(e => {
return e.tagName == 'DIV'
});
const byId = [...elems].filter(e => {
return e.id == 'div1'
});
const byClass = [...elems].filter(e => {
return e.className == 'class1'
});
console.log(byClass)
<div id="div1" class="class1"></div>
<div id="div2" class="class1"></div>
<div id="div3" class="class2"></div>
<p id="p1" class="class1"></p>
<p id="p2" class="class2"></p>
<p id="p3" class="class2"></p>
you can bine Array.filter() with Element.matches()
var x = document.querySelectorAll("div, p");
var divs = x.filter(y => y.matches("div"));
// for p tags
var paragraphs = x.filter(y => y.matches("p"));
//for both div and p tags
var mix = x.filter(y => y.matches("div, p"));
querySelectorAll returns a NodeList not an array.
You'll need to convert it to an array
var arr = Array.prototype.slice.call(x);
var divs = arr.filter(el => { return el.tagName == 'DIV' });
A very naive approach:
function get(selector) {
const els = document.querySelectorAll(selector);
return {
selector,
length: els.length,
get: i => els[i],
[Symbol.iterator]: () => els[Symbol.iterator](),
filter: f => get(selector + ", " + f)
};
}
Usable as:
const menus = get(".menu");
for(const el of menus) console.log(el);
console.log(menus.filter("div").get(0));