views:

52

answers:

3

Possible Duplicate:
jQuery filtering selector to remove nested elements matching pattern.

I have a hierarchy of groups. Something like:

<div class="group">
    <span class="child"></span>
    <div class="group">
        <span class="child"></span>
        <span class="child"></span>
        <span class="child"></span>
    </div>
    <span class="child"></span>
    <span class="child"></span>
    <div>This child is farther down <span class="child"></span></div>
</div>

How can I select the children in each group, without selecting any subgroup's children?

$(".group").each(function() {
    // Wrong, click fires twice (the 1st level group selects 2nd level children)
    var children = $(this).children(".child");

    // Wrong, click fires twice
    children = $(this).children(":not(.group) .child");

    // How can I properly do this??

    children.click(function() {
        alert("children.click");
    });
});

I've also tried find() instead of children() but I can't seem to get this to work correctly. Also, I can't use direct children (or >) because the descendants could be inside other non-.gorup HTML tags (i.e. several DOM levels down).

+1  A: 

If you want only the direct children of a group you can try something like:

$('.group > .child').click(function(){
    alert('You clicked on: '+$(this).text());
});

See documentation at jQuery: child-selector

EDIT: else you might want to check out the duplicate question posted by gnarf

Dan Manastireanu
I added some more info which you may have missed. The children could be inside other non-.group HTML tags.
Nelson
+1  A: 

If .child is always a direct descendant of its group, then > selector will work, as noted. Otherwise, you can filter set with a function

var group = this;
$(group).find('.child').filter(function() {
    // check if current element belongs to our group
    return $(this).closest('.group')[0] == group;
})

An example

Nikita Rybak
I think both gnarf and you have it right. I'm thinking yours would be faster because it only has to go up the tree a few nodes, but it does have to do it for every child so I'm not completely sure. This is a closer version to what I was looking for: http://jsfiddle.net/KxnTZ/2/
Nelson
@Nelson Version with _not_ also processes every child, so I think they should have comparable speeds. Although, it depends on how effective is substruction of sets in jquery: if _a.not(b)_ means every element of _a_ is compared to every element of _b_, that would be bad.
Nikita Rybak
So my REAL problem was I actually needed to select a checkbox inside the span. So I had something comparable to `$(group).find(".child").filter(...).find(":checkbox")`. Of course that last find didn't stay within the boundaries since we already filtered before. Your example (which worked) helped me find this error.
Nelson
The `.find().not(.find())` seems MUCH faster: http://jsperf.com/selector-test-find-not
gnarf
@gnarf Thanks! Should bookmark that website.
Nikita Rybak
@gnarf - I'll go with not() then since the syntax is also easier on the eyes. I really should be giving you the correct answer, though you were right it was a duplicate.
Nelson
A: 

Try this, it is also very readable:

$(".group").each(function() {
  var allChilds = $(this).find('.child');
  var subChilds = $(this).find('.group .child');

  var firstChilds = allChilds.not(subChilds);
  firstChilds.css({ color: 'red' });
});
Josiah Ruddell