Check if an element is a child of a parent
JavascriptJqueryJavascript Problem Overview
I have the following code.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>
<div id="hello">Hello <div>Child-Of-Hello</div></div>
<br />
<div id="goodbye">Goodbye <div>Child-Of-Goodbye</div></div>
<script type="text/javascript">
<!--
function fun(evt) {
var target = $(evt.target);
if ($('div#hello').parents(target).length) {
alert('Your clicked element is having div#hello as parent');
}
}
$(document).bind('click', fun);
-->
</script>
</html>
I expect only when Child-Of-Hello
being clicked, $('div#hello').parents(target).length
will return >0.
However, it just happen whenever I click on anywhere.
Is there something wrong with my code?
Javascript Solutions
Solution 1 - Javascript
If you are only interested in the direct parent, and not other ancestors, you can just use parent()
, and give it the selector, as in target.parent('div#hello')
.
Example: http://jsfiddle.net/6BX9n/
function fun(evt) {
var target = $(evt.target);
if (target.parent('div#hello').length) {
alert('Your clicked element is having div#hello as parent');
}
}
Or if you want to check to see if there are any ancestors that match, then use .parents()
.
Example: http://jsfiddle.net/6BX9n/1/
function fun(evt) {
var target = $(evt.target);
if (target.parents('div#hello').length) {
alert('Your clicked element is having div#hello as parent');
}
}
Solution 2 - Javascript
.has()
seems to be designed for this purpose. Since it returns a jQuery object, you have to test for .length
as well:
if ($('div#hello').has(target).length) {
alert('Target is a child of #hello');
}
Solution 3 - Javascript
Vanilla 1-liner for IE8+:
parent !== child && parent.contains(child);
Here, how it works:
function contains(parent, child) {
return parent !== child && parent.contains(child);
}
var parentEl = document.querySelector('#parent'),
childEl = document.querySelector('#child')
if (contains(parentEl, childEl)) {
document.querySelector('#result').innerText = 'I confirm, that child is within parent el';
}
if (!contains(childEl, parentEl)) {
document.querySelector('#result').innerText += ' and parent is not within child';
}
<div id="parent">
<div>
<table>
<tr>
<td><span id="child"></span></td>
</tr>
</table>
</div>
</div>
<div id="result"></div>
Solution 4 - Javascript
If you have an element that does not have a specific selector and you still want to check if it is a descendant of another element, you can use jQuery.contains()
> jQuery.contains( container, contained )
> Description: Check to see if a DOM element is a descendant of another DOM element.
You can pass the parent element and the element that you want to check to that function and it returns if the latter is a descendant of the first.
Solution 5 - Javascript
Ended up using .closest() instead.
$(document).on("click", function (event) {
if($(event.target).closest(".CustomControllerMainDiv").length == 1)
alert('element is a child of the custom controller')
});
Solution 6 - Javascript
You can get your code to work by just swapping the two terms:
if ($(target).parents('div#hello').length) {
You had the child and parent round the wrong way.
Solution 7 - Javascript
Without jquery
target.matches()
with :scope
If you want to see if the target element has a parent which matches some selector use the .matches()
method on the target and pass the selector followed by the :scope
pseudo class.
The :scope
here refers to the target element so you can use the in a :where
pseudo class to help you write out a clean selector.
In the following example we will match all target elements which are a decedent of an a
, button
, or summary
element.
const app = document.getElementById("app");
app.addEventListener("click", (event) => {
if (
event.target.matches(
":where(a, button, summary) :scope"
)
) {
console.log("click", event.target.parentNode.tagName);
}
});
<div id="app">
<button>
<span>Click Me</span>
</button>
<a href="#">
<span>Click Me</span>
</a>
<details>
<summary>
<span>Click Me</span>
</summary>
</details>
<span>Click Me</span>
<div>
Note the selector :where(a, button, summary) :scope
could also have been written as:
a :scope,
button :scope,
summary :scope
parent.contains()
If you are interested in seeing if the target element is a child of a specific element use .contains()
on the potential parent element:
const app = document.getElementById("app");
const button = document.getElementById("button");
app.addEventListener("click", (event) => {
if (button.contains(event.target)) {
console.log("click");
}
});
<div id="app">
<button id="button">
<span>Click Me</span>
</button>
<span>Click Me</span>
<div>
Solution 8 - Javascript
In addition to the other answers, you can use this less-known method to grab elements of a certain parent like so,
$('child', 'parent');
In your case, that would be
if ($(event.target, 'div#hello')[0]) console.log(`${event.target.tagName} is an offspring of div#hello`);
Note the use of commas between the child and parent and their separate quotation marks. If they were surrounded by the same quotes
$('child, parent');
you'd have an object containing both objects, regardless of whether they exist in their document trees.
Solution 9 - Javascript
To know more background info on Aleksandr Makov's answer, checking the below page might be helpful.
https://developer.mozilla.org/en-US/docs/Web/API/Node/contains
> Node.contains()
> The contains() method of the Node interface returns a boolean value indicating whether a node is a descendant of a given node, that is the node itself, one of its direct children (childNodes), one of the children's direct children, and so on.
It means, the answer is not using a reclusive function.