I’d like to propose an option to all DOM functions that select multiple elements (i.e. getElementsBy*
, maybe also querySelectorAll
?) to limit which elements they can find.
As a simple example:
<div id="context">
<ul>
<li id="A"></li>
<li id="B"></li>
<li id="C">
<ul>
<li id="CA"></li>
<li id="CB"></li>
</ul>
</li>
<li id="D"></li>
</ul>
</div>
I’d like to select all <li>
elements inside <div id="context">
but not <li>
inside other <li>
. Maybe like so:
const contextElement = document.getElementById('context')
contextElement.getElementsByTagName('li', { flat: true })
A more flexible variation could allow you to specify elements whose descendants should be ignored, if those elements are very different:
contextElement.getElementsByTagName('li', { ignoreDescendantsOf: 'li' })
It would be nice if ignoreDescendantsOf
was a CSS selector. Otherwise just another tag name.
This is useful if one wants to select all conceptual children of a recursive structure even if the elements aren’t children in a technical sense.
One good example (and also one of my potential use-cases) would be the following XML Schema:
<xs:schema>
<xs:element name="element-a">
<xs:complexType>
<xs:sequence>
<xs:element name="element-a-a">
<xs:complexType>
<xs:sequence>
<xs:element name="element-a-a-a" />
<xs:element name="element-a-a-b" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:choice>
<xs:element name="element-a-b" />
<xs:element name="element-a-c" />
</xs:choice>
<xs:element name="element-a-d"></xs:element>
<xs:element name="element-a-e"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
When I parse this using the DOMParser
and get a reference to “element-a” I could select all element definitions that define immediate children of “element-a” like this:
elementA.getElementsByTagNameNS(ns, 'element', { flat: true })
The result would only include element-a-a
to element-a-e
, but not element-a-a-a
and element-a-a-b
because they are located inside another <xs:element>
.
Using the alternative implementation you could select all <xs:element>
elements that are not somewhere inside a <xs:choice>
element:
elementA.getElementsByTagNameNS(ns, 'element', { ignoreDescendantsOf: 'choice' })
Although it seems CSS selectors don’t support namespaces. So, I see at least a problem with this particular combination.