Given this sample markup (assuming a random number of elements between .outer
and .inner
:
<div class="outer">
<div>
<div>
<div class="inner"></div>
</div>
</div>
</div>
I can set up jQuery to select the outer and inner divs as such:
$outer = $('.outer');
$inner = $outer.find('.inner')
Works fine.
However, let's say I want to allow an unlimited nesting of this logic, so I may have this:
<div class="outer"> div a
<div class="inner"> div b
<div class="outer"> div c
<div class="inner"> div d </div>
</div>
</div>
</div>
In that situation, when selecting div a via .outer
I want to match it with only div b. In otherwords, I want to exclude ancestors of a nested .outer
ancestor.
I'd like to have parings of outer and inner(s) contained within their nesting level.
I'm hoping .filter()
could pull it off, but can't think of a selector that would work universally for unlimited nested patterns. Is it doable using a filter? Or maybe even a direct selector pattern?
UPDATE:
I think something like this could work, but not sure how one can (or if it's allowed) reference 'this' within a selector:
$outer = $('.outer');
$inner = $outer.not('this .outer').find('.inner')
UPDATE 2:
I should have mentioned this intially: .inner
will always be a descendant of .outer
but not necessarily an immediate child.
UPDATE 3:
Here's some test samples of HTML that could be used. In each case, I'd want to be able to select the .outer and pair up the .inner's it contains between itself and the nested outer. For clarity, I added names to each div (outer-x pairs with inner-x)
//sample 1
<div class="outer"> outer-a
<div>
<div class="inner"> inner-a
<div class="outer"> inner-b
<div class="inner"> inner-b </div>
</div>
</div>
</div>
<div>
<div class="inner"> inner-a </div>
</div>
</div>
//sample 2
<div class="outer"> outer-a
<div class="inner"> inner-a
<div class="outer"> inner-b
<div>
<div class="inner"> inner-b </div>
</div>
</div>
</div>
</div>
//sample 3
<div class="outer"> outer-a
<div class="inner"> inner-a
<div class="outer"> inner-b
<div class="inner"> inner-b
<div class="outer"> outer-c
<div class="inner"> inner-c</div>
</div>
</div>
</div>
</div>
</div>
//bonus sample (we're trying to avoid this)
<div class="outer"> outer-a
<div class="inner outer"> inner-a outer-b
<div class="inner"> inner-b </div>
</div>
</div>
UPDATE 4
I think I ended up going down a s开发者_如何学运维imilar path as gnarf. I ended up with this:
var $outer = $('.outer');
var $inner = $outer.find('.inner').filter(function(){
$(this).each(function(){
return $(this).closest('.outer') == $outer;
});
});
Am I on the right track there? It's not working so I assume I have a bit of a logic error still.
Here's another option. Suppose you have the .outer
o
, this will select all inner
s under it:
o.find('.inner').not(o.find('.outer .inner'))
It should work identically to gnarf's answer, but a bit simpler.
First, it finds all inner
s under this outer
.
Next, remove all inners
that are descendants of other outers
Interactive working example: http://jsfiddle.net/Zb9gF/
Selector performance seems to be much better using this method as opposed to the .filter()
as well: http://jsperf.com/selector-test-find-not
$('.outer').children('.inner');
That would select any inner
that sits immediately below an outer
. I'm not really clear on which div you're trying to select for. Is it a, b, c, or d? Having something called outer nested within something called inner doesn't make a whole lot of sense. Maybe if you could provide a more specific example?
If the .inner
are always direct children of .outer
s - children()
is probably your best bet (jasongetsdown's answer)
If you need something that looks even deeper, you could do something like this:
var $outer = $('.outer').first(); // grab the first .outer
$outer.find('.inner').filter(function() {
// only if the closest parent .outer is the same as the .outer we are looking in
return $(this).closest('.outer').get(0) == $outer.get(0);
}).css('border','1px solid #000');
jsfiddle demo
You could use some css magic:
$('.outer>.inner')
Shold give you only first level of .inner
elements. :)
If assume correctly you want to select all .inner
that is beneath an .outer
, except if there is an .outer
inbetween, perhaps following will work (untested):
$('.outer:not(.inner):has(:not(.outer) .inner:not(.outer), > .inner:not(.outer))');
updated after test on OP example HTML at http://jsfiddle.net/cEwBT/1/
I wonder why not to select .inner
at first, and then get closest
.outer
?
$inner = $('.inner'); $outer = $inner.closest('.outer');
in case some inner blocks could be not within outer blocks at all, use this first line instead
$inner = $('.outer .inner');
精彩评论