jQuery find closest previous sibling with class
Solution 1
Try:
$('li.current_sub').prevAll("li.par_cat:first");
Tested it with your markup:
$('li.current_sub').prevAll("li.par_cat:first").text("woohoo");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="par_cat"></li>
<li class="sub_cat"></li>
<li class="sub_cat"></li>
<li class="par_cat">// this is the single element I need to select</li>
<li class="sub_cat"></li>
<li class="sub_cat"></li>
<li class="sub_cat current_sub">// this is where I need to start searching</li>
<li class="par_cat"></li>
<li class="sub_cat"></li>
<li class="par_cat"></li>
</ul>
will fill up the closest previous li.par_cat
with "woohoo".
Solution 2
Try
$('li.current_sub').prev('.par_cat').[do stuff];
Solution 3
Using prevUntil() will allow us to get a distant sibling without having to get all. I had a particularly long set that was too CPU intensive using prevAll().
var category = $('li.current_sub').prev('li.par_cat');
if (category.length == 0){
category = $('li.current_sub').prevUntil('li.par_cat').last().prev();
}
category.show();
This gets the first preceding sibling if it matches, otherwise it gets the sibling preceding the one that matches, so we just back up one more with prev() to get the desired element.
Solution 4
I think all the answers are lacking something. I prefer using something like this
$('li.current_sub').prevUntil("li.par_cat").prev();
Saves you not adding :first inside the selector and is easier to read and understand. prevUntil() method has a better performance as well rather than using prevAll()
Related videos on Youtube
daulex
Updated on April 03, 2021Comments
-
daulex about 3 years
Here's the rough HTML I get to work with:
<li class="par_cat"></li> <li class="sub_cat"></li> <li class="sub_cat"></li> <li class="par_cat"></li> // this is the single element I need to select <li class="sub_cat"></li> <li class="sub_cat"></li> <li class="sub_cat current_sub"></li> // this is where I need to start searching <li class="par_cat"></li> <li class="sub_cat"></li> <li class="par_cat"></li>
I need to traverse from the
.current_sub
, find the closest previous.par_cat
and do stuff to it..find("li.par_cat")
returns the whole load of.par_cat
(I've got about 30 on the page). I need target the single one. -
daulex about 14 yearsthank you Karim. This worked well too, but I assume the .prev() would eat less resources, as .prevAll would get ALL the previous matched elements and then would filter the one I need. Accepting Ed's answer.
-
daulex about 14 yearsActually, after a bit of texting, the .prev() failed in a few instances. .prevAll with :first, worked every time. Thank you.
-
David Hobs almost 12 yearsWait, what? Doesn't this only check the immediately preceding element? Thus your code would return null? - Here it is tested on jsFiddle: jsfiddle.net/Y2TEH
-
David Hobs almost 12 years.prev() only checks the immediately preceding element. I added the comment to the answer below along with the jsFiddle exemplifying. After looking around, this is the best answer as although it has to cycle through all the elements, it doesn't require two functions to grab all then filter to find it.
-
Ed James almost 12 years@DavidHobs I wrote this two years ago.... I certainly would use prevAll() these days.
-
NReilingh about 11 yearsDoes this mean
:first
is working on a list of returned elements that starts closest to the selected object (as opposed to top to bottom relative to the page)? -
Johansrk about 10 yearsyeah the :first is needed, otherwise all prev will be selected. Thanks a lot for this answer
-
Hugo Zink over 8 years@EdWoodcock consider updating your answer, in that case.
-
Accountant م almost 7 yearsThank you very much for the very useful answer. Can you please answer @NReilingh question because it's really confuses me. Isn't
:first
a CSS selector that selects the first element in DOM (e.gdiv.red:first
will select the first red DIV in the DOM) did jQuery parse the selector differently ? -
JasonWilson over 3 yearsI tried this one first, what happened is prevUntil returns many elements, then it gets prev() for each of the many elements. The desired result is one element
-
TylerH over 3 years@Accountantم There is no CSS selector called
:first
. -
Accountant م over 3 years@TylerH oh now that makes sense, thanks. It's a jQuery only selector and it's free to parse it as it likes :D.