jquery move .detail rows after .group row

Screenshot

How can I make the following code move all the detail after its group row

                  $('#div-formcontent').find('tr.detail').each(function(){
                                          //$(this).hide()
                                          $(this).insertAfter($(this).next('tr.group'))
                                    
                                    })
The code moves the first .detail row but not the remaining detail rows

Screenshot
maxdbaseAsked:
Who is Participating?
 
David S.Commented:
jQuery's "next" method means the very next, as in just 1 element. Specifying a selector for it is effectively just a condition. What you want is to use "nextAll" with "eq".

                                    $('#div-formcontent').find('tr.detail').each(function(){
                                          //$(this).hide()
                                          $(this).insertAfter($(this).nextAll('tr.group').eq(0))
                                    
                                    })

Open in new window

0
 
Julian HansenCommented:
Can we see the source for the table.
0
 
Julian HansenCommented:
I don't understand how the accepted solution is different from the original code

.nextAll(selector).eq(0)
is the same as
next(selector)

nextAll(n) finds all the matching selector siblings
next(n) finds the first matching sibling

When you use .eq(0) on the results of nextAll() you are taking the first result returned - which is the next() element.

So either the original code works or the question has not been answered.

Consider this example that shows three tables (original, next() and nextAll().eq(0). Note how the latter two are the same after applying next() and nextAll().eq(0) respectively.

HTML
<div class="row">
  <div class="col-md-4">
    <h2>Original</h2>
    <table class="table" id="table3">
      <tr>
        <td>Non Detail Row</td>
      </tr>
      <tr class="detail">
        <td>Detail Row</td>
      </tr>
      <tr class="group">
        <td>Group Row</td>
      </tr>
      <tr>
        <td>Non Detail Row 2</td>
      </tr>
      <tr class="detail">
        <td>Detail Row 2</td>
      </tr>
      <tr class="group">
        <td>Group Row 2</td>
      </tr>
      <tr>
        <td>Non Detail Row 3</td>
      </tr>
      <tr class="detail">
        <td>Detail Row 3</td>
      </tr>
      <tr class="group">
        <td>Group Row 3</td>
      </tr>
    </table>
  </div>
  <div class="col-md-4">
    <h2>Next()</h2>
    <table class="table" id="table1">
      <tr>
        <td>Non Detail Row</td>
      </tr>
      <tr class="detail">
        <td>Detail Row</td>
      </tr>
      <tr class="group">
        <td>Group Row</td>
      </tr>
      <tr>
        <td>Non Detail Row 2</td>
      </tr>
      <tr class="detail">
        <td>Detail Row 2</td>
      </tr>
      <tr class="group">
        <td>Group Row 2</td>
      </tr>
      <tr>
        <td>Non Detail Row 3</td>
      </tr>
      <tr class="detail">
        <td>Detail Row 3</td>
      </tr>
      <tr class="group">
        <td>Group Row 3</td>
      </tr>
    </table>
  </div>
  <div class="col-md-4">
    <h2>NextAll().eq(0)</h2>
    <table class="table" id="table2">
      <tr>
        <td>Non Detail Row</td>
      </tr>
      <tr class="detail">
        <td>Detail Row</td>
      </tr>
      <tr class="group">
        <td>Group Row</td>
      </tr>
      <tr>
        <td>Non Detail Row 2</td>
      </tr>
      <tr class="detail">
        <td>Detail Row 2</td>
      </tr>
      <tr class="group">
        <td>Group Row 2</td>
      </tr>
      <tr>
        <td>Non Detail Row 3</td>
      </tr>
      <tr class="detail">
        <td>Detail Row 3</td>
      </tr>
      <tr class="group">
        <td>Group Row 3</td>
      </tr>
    </table>
  </div>
</div>

Open in new window

jQuery
<script>
$(function() {
  $('#table1').find('tr.detail').each(function(){
    $(this).insertAfter($(this).next('tr.group'))
  })
  $('#table2').find('tr.detail').each(function(){
    $(this).insertAfter($(this).nextAll('tr.group').eq(0));
  })
});
</script>

Open in new window

Working sample here
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
maxdbaseAuthor Commented:
NextAll is what I am after.
I did not know that existed.
Next was getting the first of the collection and
I needed All of the collection to move.
0
 
maxdbaseAuthor Commented:
This is what I am after...
$('#table2').find('tr.detail').each(function(){
    $(this).insertAfter($(this).nextAll('tr.group').eq(0));
  })

Thanks for helping.
I was stuck now all good.
0
 
Julian HansenCommented:
Let me repeat this
next() is exactly the same as nextAll().eq(0)

That is my point - you are not using nextAll() when you add .eq(0) to it because you are taking the set of elements returned by nextAll() and reducing it to the first element which is identical to next()

Therefore, I am saying I don't think you are understanding the problem because the solution you are now using is identical to what you already had -  refer my example.
0
 
maxdbaseAuthor Commented:
Thank you for clarifying.
So nextAll() without the eq(0) returns the full set?
so I can do .each()?

If so, that will do what I need.
My system for this client is tied up by another developer until tonight.
I will test then and can advise.

Sorry for any mis-communication.  I am just happy to get some direction on this.
It's a big deal on my end and I have been struggling with it for weeks.
0
 
David S.Commented:
maxdbase, you're welcome.

Since the question of how the solution works has been raised, I'll explain more. In some cases next(x) and nextAll(x).eq(0) will yield the same result, but not in this one. Without selectors, next() and nextAll().eq(0) are effectively the same (the former is likely to execute faster than the latter though). However, when a selector is specified, next(x) checks if the next element matches the selector, if not, no element is matched; it does not go on to check any following siblings. On the other hand, when a selector is specified, nextAll(x) finds all following siblings and then filters them based on the selector, then when paired with eq(0), we select the first such element, which might be the same as just using next(x), but if the first following sibling does not match "x," using nextAll(x) will find one that does, if there is one.

In this specific case we don't even want to match multiple elements there, because an element can only be moved after one element. Remember we're looping through all of the rows with a certain class.

The documentation is also available:
http://api.jquery.com/next/
http://api.jquery.com/nextAll/
0
 
Julian HansenCommented:
This is precisely why I asked to see the actual code of the table. There are other ways of solving this that don't require the use of next() or nextAll() which might be better suited to the problem
0
 
maxdbaseAuthor Commented:
Your input led me to re-thinking the DOM and the jquery code.
I landed on adding an attribute into the tr's then using closest and find.
Thanks again,
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.