From page=$("#page")
I want to get all the specified SVGs but not the subsequent inner ones.
<div id="page">
<div ...>
<svg> /* THIS ONE */
<rect ...>
<circle ...>
<svg> /* NOT THIS ONE */
<foo> ... </foo>
</svg>
</svg>
</div>
<div ...>
<div ...>
<svg> /* THIS ONE */
<rect ...>
<circle ...>
<svg> /* NOT THIS ONE */
<foo> ... </foo>
</svg>
</svg>
</div>
</div>
</div>
EDIT I've updated the markup to clearly specify what I mean.
One solution is to use :not(svg svg)
which i find ugly and performance heavy.
After updated question
The only solutions are
$('#page svg:not(:has(svg))');
and your own
$('#page svg:not(svg svg)');
Performance-wise (check out the test) they are about the same with no clear winner
original answer
For the particular example
$('#page > svg:first')
or
$('#page svg:first')
will suffice.
But consider the following case
<div id="page">
<div>
<p>
<svg id="svg-1"></svg>
</p>
<svg id="svg-2"></svg>
</div>
</div>
Is this case possible (both svgs wrapped in something else) ? and if so, do you want #svg-2
?
This case is not handled by the >
version at all, and the$('#page svg:first')
version will return the #svg-1
You could use the following:
$(page).children(svg).first()
Which will get you the first svg, in this case the outer most one, but might also still be performance heavy if that is part of your concern.
If you know it's always going to have a <div>
parent, you could do this (which avoids having to know how many elements are between #page
and div
):
#page div>svg
Just get the first child level with >
.
#page > svg