jQuery find closest previous sibling with class

JqueryHtmlTraversalTree Traversal

Jquery Problem Overview


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.

Jquery Solutions


Solution 1 - Jquery

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 - Jquery

Try

$('li.current_sub').prev('.par_cat').[do stuff];

Solution 3 - Jquery

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 - Jquery

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()

Solution 5 - Jquery

You can follow this code:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
    $(document).ready(function () {
        $(".add").on("click", function () {
            var v = $(this).closest(".division").find("input[name='roll']").val();
            alert(v);
        });
    });
</script>
<?php

for ($i = 1; $i <= 5; $i++) {
    echo'<div class = "division">'
        . '<form method="POST" action="">'
        . '<p><input type="number" name="roll" placeholder="Enter Roll"></p>'
        . '<p><input type="button" class="add" name = "submit" value = "Click"></p>'
        . '</form></div>';
}
?>

You can get idea from this.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondaulexView Question on Stackoverflow
Solution 1 - Jquerykarim79View Answer on Stackoverflow
Solution 2 - JqueryEd JamesView Answer on Stackoverflow
Solution 3 - JqueryeprothroView Answer on Stackoverflow
Solution 4 - JqueryTom McDonoughView Answer on Stackoverflow
Solution 5 - JqueryAL MaMunView Answer on Stackoverflow