In jQuery you can call closest
to find the closest parent.
If I have a a
in a li
in a ul
in a td
in a table
. I want to find out if the ul
parent is closer than the table
parent. Obviously in this case the answer is obvious.
If I run $('a').closest('table').length
or $('a').closest('ul').length
both return 1.
I would like to find out which parent is closer in the DOM.
Technically if there were a method than in this case $('a').closer('ul', 'table')
would return the ul
because it is closer in the DOM.
<table> <!-- Is this closer -->
<tr>
<td>
<ul> <!-- Or is this closer -->
<li>
<a href="#">A button</a>
</li>
</ul>
</td>
</tr>
</table>
In jQuery you can call closest
to find the closest parent.
If I have a a
in a li
in a ul
in a td
in a table
. I want to find out if the ul
parent is closer than the table
parent. Obviously in this case the answer is obvious.
If I run $('a').closest('table').length
or $('a').closest('ul').length
both return 1.
I would like to find out which parent is closer in the DOM.
Technically if there were a method than in this case $('a').closer('ul', 'table')
would return the ul
because it is closer in the DOM.
<table> <!-- Is this closer -->
<tr>
<td>
<ul> <!-- Or is this closer -->
<li>
<a href="#">A button</a>
</li>
</ul>
</td>
</tr>
</table>
Share
Improve this question
edited Mar 6, 2016 at 23:49
Johnston
asked Mar 6, 2016 at 23:40
JohnstonJohnston
20.9k22 gold badges75 silver badges124 bronze badges
4
- 1 I think you should post a snippet of the HTML that you are referring to. It will make things clearer to everyone. – bob.mazzo Commented Mar 6, 2016 at 23:45
-
1
1. As bob has mentioned, HTML is needed to determine position and relation of the elements/nodes within the DOM. 2. All elements (except the root which is
<html>
has only one parent. How can an element have more than one parent? What you mean is ancestors. – zer00ne Commented Mar 6, 2016 at 23:51 -
@zer00ne: It's jQuery's fault: the function to get all ancestors is called
.parents()
. – Amadan Commented Mar 6, 2016 at 23:54 -
@Amadan I guess
.ancestors()
would be too verbose. – zer00ne Commented Mar 6, 2016 at 23:56
5 Answers
Reset to default 6You can list multiple element selectors to the closest
function, it will only find the closest of one of them:
$('a').closest('table, ul')
Example:
$(document).on("click", function( event ) {
$(event.target).closest("li, b").toggleClass("hilight");
});
.hilight{
background: rgba(255, 0, 0, 0.5);
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><b>Click me!</b></li>
<li>You can also click this line <b>or click me!</b></li>
</ul>
Use .parents()
. It returns a list of all parents that are ordered from closest to farthest.
The difference between using this and using .closest(selector)
is that it accepts a jQuery object instead of a selector string, which has to be hard coded. Meanwhile jQuery objects can be collections and so can be generated on the fly.
(function($) {
$.fn.getClosest = function(testElements) {
var element = $(this);
var parents = element.parents();
var indexClosest = Number.MAX_VALUE;
testElements.each(function() {
var index = parents.index($(this));
if (index > -1 && index < indexClosest)
indexClosest = index;
});
return parents.eq(indexClosest);
};
})(jQuery);
Use the function like this:
$("a").getClosest($("table, ul"))
Fiddle with advanced use case
I like Fabian's answer; but to actually measure the distance, you can use this:
var $parentsUntilTable = $('li').parentsUntil('table');
var $parentsUntilUl = $('li').parentsUntil('ul');
console.log($parentsUntilTable.length < $parentsUntilUl.length
? 'table is closer'
: 'ul is closer');
<!-- results pane console output; see http://meta.stackexchange./a/242491 -->
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<ul>
<li>
</li>
</ul>
</td>
</tr>
</table>
Here is a simple implementation of the .closer()
method that returns the selector that is closest to the given element:
$.fn.closer = function(varargs) {
var $elem = $(this);
while ($elem.length) {
for (var i = 0, len = arguments.length; i < len; i++) {
if ($elem.is(arguments[i])) {
return arguments[i];
}
}
$elem = $elem.parent();
}
return null;
};
See it in action on jsFiddle.
An element only has one parent node, above those are ancestor nodes.
From here: https://stackoverflow./a/15149590/1876047 - you can use
$(elem1).offset().top - $(elem2).offset.().top
As both nodes are ancestors of the element you are considering, the one furthest from the root of the DOM tree is the closet to your element.
So if the above difference is greater than 0, then elem2 is closest, otherwise elem1 is closest.