Reputation: 1180
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
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
Reputation: 206078
To answer exactly what you asked:
data-*
attribute of each .parent
start
event use Use jQuery's .detach()
to store the child element(s) into data.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