16

I wonder how I in the best way can see if a container div contains a child element. I have a click event that fires on a child of either div id=unread or div id=read. I want to check where this child is.

Something like this is what I'm thinking:

if ($("#unread").find($(this)))
    alert("unread");
else
    alert("read");

Edit: $(this) is a descendants two levels from #unread or #read.

Regards

user822448
  • 673
  • 2
  • 8
  • 18
  • possible duplicate of http://stackoverflow.com/questions/648004/what-is-fastest-children-or-find-in-jquery – Vivek Jun 30 '11 at 06:28

5 Answers5

16

Make use of : .children()

if( $("#unread").children().length > 0)
    alert("unread");
else
    alert("read");

EDIT

if($(event.target).closest('#unread').length > 0)
    alert('unread');
else
    alert('read');
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • Oh, I forgot to say that $(this) is a descendants two levels from #unread or #read. So the parent of the parent of this should be either unread or read – user822448 Jun 30 '11 at 06:28
  • This don't work, since the clicked $(this) is two levels from #unread. It's also not the single child two levels from #unread. – user822448 Jun 30 '11 at 06:36
3

I think just adding .length should work:

if ($("#unread").find($(this)).length > 0)
    alert("unread");
else
    alert("read");
Brad Mace
  • 27,194
  • 17
  • 102
  • 148
  • There are multiple childs looking like $(this), that is two levels from #unread or #read. Therefore children will not identify $(this), i guess. – user822448 Jun 30 '11 at 06:39
  • This doesn't answer the question: the OP asks how to check if one div is a (grand)child of another, not to just check if one div has any children at all. – nnnnnn Jun 30 '11 at 06:47
  • @nnn- yes, **now** it says that – Brad Mace Jun 30 '11 at 06:48
  • it *always* said that: the second and third sentences and the example code make it clear the click event is on the descendent div and the question is how to figure out which ancestor it belongs to; the edit just clarified that the relationship is exactly two generations apart. – nnnnnn Jun 30 '11 at 23:42
2

Go backwards from $(this) to look for #unread as an ancestor using closest:

if($(this).closest('#unread').length > 0)
    alert('unread');
else
    alert('read');

Depending on your HTML structure, this will be faster than searching all the children of #unread to find this. The speed difference probably won't matter that much though but you should be aware of the option of going backwards and the possible benefits of doing so.

Checking for the ancestor might be a better match for your intent as well: you have this in hand and what you really want to know is "is it inside #unread?". Using closest to go back up the DOM tree exactly matches the question you're asking.

If for some reason you're dead set on starting at #unread and looking at its descendants, then you can use find:

if($('#unread').find(this))
    alert('unread');
else
    alert('read');

But this approach will only work if you're using at least jQuery 1.6.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
2

Use .closest() or .parents() to search up the tree from the clicked element:

if ($(this).closest("#unread").length == 1)
   // etc

Otherwise, are you interested in a non-jQuery answer? Given you've said the div with the click event is exactly two levels below the "read" or "unread" divs you could just do this:

if (this.parentNode.parentNode.id === "unread")
   alert("unread");
else
   alert("read");

// or just alert(this.parentNode.parentNode.id);
nnnnnn
  • 147,572
  • 30
  • 200
  • 241
1

I wonder how I in the best way can see if a container div contains a child element.

Use $.contains(), especially if performance is a concern. From the docs:

jQuery.contains( container, contained )

Returns: Boolean

Description: Check to see if a DOM element is a descendant of another DOM element.

It's more efficient than .find(), .children(), or .closest(), as others have recommended. Be aware, however, that it only accepts DOM elements as parameters, not jQuery objects (which is part of why its performance is better).

In your case, you could do this in your click event handler:

if ($.contains($("#unread")[0], this)) {
    alert("unread");
} else {
    alert("read");
}

EDIT: Upon thinking about this again, it's probably more intuitive to search up from the clicked element, rather than down from the parent element, and performance wouldn't normally be a concern in a click event handler. That is, I would opt to use the .closest() method (as suggested by @nnnnnn and @mu is too short), so my click event handler would contain:

if ($(this).closest("#unread").length > 0) {
    alert("unread");
} else {
    alert("read");
}
Sean the Bean
  • 5,222
  • 5
  • 38
  • 40