Specification
The inputs to this function would be two selectors. This implies that there is no pre-existing DOM element, which is an important constraint in this problem. The question that the function should answer is "would all elements matched by Needle be matched by Haystack?" In other words, I am trying to determine if the set of elements matched by Needle represents a subset of the set of elements matched by Haystack. The following table of examples should clarify the specification:
Needle | Haystack | Matches? | Explanation / Counterexample
-----------------+------------------+----------+--------------------------------
div | * | yes | Any div is something.
div | div | yes | Any div is a div.
div | div:not(.classy) | no | <div class="classy">
div | .classy | no | <div>
div.classy | div | yes | Any classy div is a div.
div.classy | div.classy | yes | Any classy div is a classy div.
div.classy | div:not(.classy) | no | <div class="classy">
div.classy | .classy | yes | Any classy div is classy.
div:not(.classy) | div | yes | Any non-classy div is a div.
.classy | div | no | <span>
.classy | div.classy | no | <div>
:not(.classy) | div | no | <span>
div div | div | yes | Any nested div is a div.
div | div div | no | Not all divs are nested.
A naive solution would create a temporary DOM element based on the Needle and call document.querySelector()
with the Haystack as argument. The solution would iterate over the list and return true
if it finds the generated element. Caveats:
- Just because one element matching the Needle happens to match the Haystack does not mean all possible elements matching the Needle will match the Haystack. It is difficult to make the representative element as general as possible.
- It is difficult to generate an element matching a non-simple selector, because the entire tree up to that element would have to be recreated to accomodate it.
- Inserting temporary elements into the DOM and not properly cleaning them up can interfere with site logic.
A complete solution should avoid creating temporary DOM elements. The solution would ideally rely on the rendering engine's built-in CSS matching mechanisms. If the solution makes use of vendor-specific functions, those functions should be recreatable in pure JavaScript on the current version of other browsers (where IE10 can be considered the "current" IE).
Motivation
The purpose of the function is to query the document stylesheets for all rules that apply to elements that would match a given selector. For example, given the following CSS:
* {
color: yellow;
}
div {
background-color: black;
}
.classy {
margin: 5px;
}
one would expect the following:
Selector | Matched rules
-----------+-----------------------------------------------------
div.classy | color: yellow; background-color: black; margin: 5px;
div | color: yellow; background-color: black;
.classy | color: yellow; margin: 5px;
A naive solution would iterate over the document stylesheets block by block and perform exact string matches on the selectors. These would yield fewer rules than computed by the CSS engine. A complete solution would require the function described in the above section.
Similar questions
I believe this asker wanted a similar solution, but the question was not understood.
Thank you for your time!