arifpervez arifpervez - 4 months ago 30
jQuery Question

Condition in nextUntil toggle in JQuery

I am using

nextUntil
method to toggle my table rows values. It is working fine unless in the last link of any levels. For example (please see the table), when I am clicking the Level 1.2.2 (class 3), it is hiding all the bottom rows because it is looking level 3 below which is right. I believe I need a condition to add to achieve this. But don't know how to add condition.

I want when any class level below (less than) from clicked class level, it will stop toggling. Also, is there any other way I can achieve these because it is a slow process.

Here is the code:

<table id=test>
<tr class=1><td>Level 1</td></tr>
<tr class=2><td>Level 1.1</td></tr>
<tr class=3><td>Level 1.1.1</td></tr>
<tr class=3><td>Level 1.1.2</td></tr>
<tr class=2><td>Level 1.2</td></tr>
<tr class=3><td>Level 1.2.1</td></tr>
<tr class=3><td>Level 1.2.2</td></tr>
<tr class=4><td>Level 1.2.2.1</td></tr>
<tr class=4><td>Level 1.2.2.1</td></tr>
<tr class=1><td>Level 2</td></tr>
<tr class=2><td>Level 2.1</td></tr>
<tr class=3><td>Level 2.1.1</td></tr>
<tr class=3><td>Level 2.1.2</td></tr>
</table>

$(document).ready(function () {
$('tr.3').click(function () {
$(this).nextUntil('tr.3').slideToggle();
});
});


Thanks in advance!

Answer

As you can't change your HTML structure, here's an alternative:

$('tr').click(function(event) {
  event.stopPropagation();
  var currentLevel = parseInt($(this).attr('class')),
    state = $(this).hasClass('hiding'),
    nextEl = $(this).next(),
    nextLevel = parseInt(nextEl.attr('class'));
  while (currentLevel < nextLevel) {
    nextEl.toggle(state);
    nextEl = nextEl.next();
    nextLevel = parseInt(nextEl.attr('class'));
  }
  $(this).toggleClass('hiding');
});
tr[class^="2"] td {
  padding-left: 20px;
}
tr[class^="3"] td {
  padding-left: 40px;
}
tr[class^="4"] td {
  padding-left: 60px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="test">
  <tr class="1">
    <td>Level 1</td>
  </tr>
  <tr class="2">
    <td>Level 1.1</td>
  </tr>
  <tr class="3">
    <td>Level 1.1.1</td>
  </tr>
  <tr class="3">
    <td>Level 1.1.2</td>
  </tr>
  <tr class="2">
    <td>Level 1.2</td>
  </tr>
  <tr class="3">
    <td>Level 1.2.1</td>
  </tr>
  <tr class="3">
    <td>Level 1.2.2</td>
  </tr>
  <tr class="4">
    <td>Level 1.2.2.1</td>
  </tr>
  <tr class="4">
    <td>Level 1.2.2.1</td>
  </tr>
  <tr class="1">
    <td>Level 2</td>
  </tr>
  <tr class="2">
    <td>Level 2.1</td>
  </tr>
  <tr class="3">
    <td>Level 2.1.1</td>
  </tr>
  <tr class="3">
    <td>Level 2.1.2</td>
  </tr>
</table>

Similar to Thor84no's answer, but simpler, IMO.