The DOM version of "empty" is that there are no child nodes, which you can check in various ways, probably the two most common are:
firstChild
will be null
if there are no child nodes
- The
length
of childNodes
will be 0
if there are no child nodes
So for instance, since null
is falsy and filter
works with truthy/falsy values:
const allEmpty = [...document.querySelectorAll('*')].filter(el => !el.firstChild);
(Note that querySelectorAll
returns a NodeList
and NodeList
doesn't have a filter
method, so I used spread notation there to create an array from the NodeList
[since NodeList
s are iterable according to the spec now; but see this answer about ensuring that NodeList
is iterable in your environment].)
Question #2: Will this logic traverse all children too?
querySelectorAll('*')
selects every element in the document, many of which will be inside others also on the list.
Question #3: Could we make this querySelector for only blocklevel elements?
You can certainly tailor it according to the current specification and the default display
browsers apply to them by doing a list of tag, such as querySelectorAll("div, p, h1"/*...*/)
. But that doesn't tell you what's a block element on that page, since CSS can change the display
of elements. To get up-to-date information, you'd need to use getComputedStyle
on each element after selecting it and check the display
of the result.
Building a list of all of the elements on a page may not be ideal, you might consider a recursive function instead:
function findEmpty(element, results = []) {
let child = element.firstChild;
if (!child) {
results.push(element);
}
while (child) {
if (child.nodeType === Node.ELEMENT_NODE) {
findEmpty(child, results);
}
child = child.nextSibling;
}
return results;
}
const allEmpty = findEmpty(document.body);
But this partially comes down to what you consider "empty." jQuery's :empty
selector is quite literal: An element is only empty if it doesn't have any child nodes. But your definition may be more loose — for instance, perhaps you want to consider an element that contains only whitespace (directly or in descendant elements) "empty" for your purposes (in which case: !el.textContent.trim()
). The first link above is to the DOM information on MDN which gives you lots to explore to determine your own "empty" if necessary.