Get most upper descendant descendant(s) in jQuery

2019-05-25 06:28发布

问题:

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.

回答1:

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



回答2:

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.



回答3:

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


回答4:

Just get the first child level with >.

#page > svg