aagjalpankaj
aagjalpankaj

Reputation: 1180

jquery sortable remove next row before sorting

I have one table containing parent and child as below. parent are sortable. When I try to sort any parent, I've to remove it's next child and insert it after it's new position.

<table>
    <tr class="parent"><td>Parent1</td></tr>
    <tr class="child nosort"><td>Child1</td></tr>
    <tr class="parent"><td>Parent2</td></tr>
    <tr class="child nosort"><td>Child2</td></tr>
    <tr class="parent"><td>Parent3</td></tr>
    <tr class="child nosort"><td>Child3</td></tr>
</table>

So if I move Parent1 after Parent2, it will look:

<table>       
    <tr class="parent"><td>Parent2</td></tr>
    <tr class="child nosort"><td>Child2</td></tr>
    <tr class="parent"><td>Parent1</td></tr>
    <tr class="child nosort"><td>Child1</td></tr>
    <tr class="parent"><td>Parent3</td></tr>
    <tr class="child nosort"><td>Child3</td></tr>
</table>

I've done with the insertion of child after sortupdate but not able to figure out how to remove child row before sort. Below if code written on start.

$('table').sortable({
    items: 'tr:not(.nosort)',
    start: function( event, ui ) {
        // Removal code of child before sort
        var objChild = ui.item.next();
        if( objChild.hasClass('child') ) {
            objChild.remove();
        }
    },
    update: function( event, ui ) {
    //  insertion code of child
    }
});

Upvotes: 0

Views: 374

Answers (2)

Tyler Petrov
Tyler Petrov

Reputation: 72

I know this is an old thread, but I think my answer could help someone out. Here's an updated version of Roko C. Buljan's post.

In this version the children aren't draggable, but the parents are. When one of the parents is dragged the children are temporarily "detached", using the built in .detach() Jquery method, and added to a global obj. Once the parents are finished dragging, than the children are added back to the DOM in the original order.

$('.parent').each(function() {
 $(this).data('$children', $(this).nextUntil('.parent'));
});

var children = {};

$('table').sortable({
  items: 'tr:not(.nosort)',
  start: function() {
    $('.parent').each(function() {
       children[this.id] = $($(this).data('$children')).detach()
    });
  },
  stop: function(event, ui) {
    $('.parent').each(function() {
       $(this).after(children[this.id]);
    });
  }
});
td {
  padding: 1rem;
  cursor: pointer;
  white-space: nowrap;
}

.red {
  background-color: red;
}

.blue {
  background-color: lightblue;
}

.green {
  background-color: green;
}
<table style="padding: 1rem">
  <tr class="parent red" id="one"><td>1 Parent</td></tr>
  <tr class="child nosort red"><td>1 Child</td></tr>
  <tr class="parent blue" id="two"><td>2 Parent</td></tr>
  <tr class="child nosort blue"><td>2 Child</td></tr>
  <tr class="parent green" id="three"><td>3 Parent</td></tr>
  <tr class="child nosort green"><td>3 Child</td></tr>
  <tr class="child nosort green"><td>3 Child</td></tr>
  <tr class="child nosort green"><td>3 Child</td></tr>
</table>

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

Upvotes: 0

Roko C. Buljan
Roko C. Buljan

Reputation: 206078

To answer exactly what you asked:

  • Store the next elements into data-* attribute of each .parent
  • On sortable start event use Use jQuery's .detach() to store the child element(s) into data.
  • On sortable stop event use .after() ti insert the previously detached elements

$('.parent').each(function(i, e) {
   $(this).data('$next', $(this).nextUntil('.parent'));
});

$('table').sortable({
  items: 'tr:not(.nosort)',
  start: function( ev, ui ) {
    $next = $(ui.item.data('$next')).detach();    
  },
  stop: function(event, ui) {
    ui.item.after($next);
  }
});
<table>
  <tr class="parent"><td>1 Parent</td></tr>
  <tr class="child nosort"><td>1 Child</td></tr>
  <tr class="parent"><td>2 Parent</td></tr>
  <tr class="child nosort"><td>2 Child</td></tr>
  <tr class="parent"><td>3 Parent</td></tr>
  <tr class="child nosort"><td>3 Child</td></tr>
</table>

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

but as you know, you could end up also having P2 P1 C1 C2 ... but that was not your question. Otherwise, to tackle with that problem the best would be to go back to the whiteboard, and simply place two <div>s inside a <td>

Upvotes: 1

Related Questions