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
You 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.com/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
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.com/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.
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.com/a/242491 -->
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<ul>
<li>
</li>
</ul>
</td>
</tr>
</table>