JSFiddle - React, Tailwind, and code Playground
by ThiefMaster
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/redmond/jquery-ui.css">
<div id="sortspace">
<div id="cat1" class="sortblock">
<table>
<thead>
<tr>
<th>dummy caption</th>
</tr>
</thead>
<tbody>
<tr data-id="1"><td><span class="sort-handle">X</span>dummy 1.1</td></tr>
<tr data-id="2"><td><span class="sort-handle">X</span>dummy 1.2</td></tr>
<tr data-id="3"><td><span class="sort-handle">X</span>dummy 1.3</td></tr>
<tr data-id="x"><td><span class="sort-handle">X</span>dummy X</td></tr>
</tbody>
</table>
</div>
<div id="cat2" class="sortblock">
<table>
<thead>
<tr>
<th>dummy caption</th>
</tr>
</thead>
<tbody>
<tr data-id="4"><td><span class="sort-handle">X</span>dummy 2.1</td></tr>
<tr data-id="5"><td><span class="sort-handle">X</span>dummy 2.2</td></tr>
<tr data-id="6"><td><span class="sort-handle">X</span>dummy 2.3</td></tr>
<tr data-id="x"><td><span class="sort-handle">X</span>dummy X</td></tr>
</tbody>
</table>
</div>
</div>
<button id="save">Save</button>
<div id="debug">
</div>
CSS
#debug { margin: 2em 1em 1em 1em; border-top: 1px solid #000; }
#sortspace > div {
margin: 1em;
border: 1px solid #000;
}
table { width: 100%; }
.sort-handle { cursor: move; margin-right: 0.5em; font-weight: bold; }
.placeholder { height: 1.5em; background: #fc0; }
.drop-target { border: 1px dashed #fa0 !important; background: #fff7cf; }
JavaScript
function dbg(txt, overwrite) {
if(overwrite) {
$('#debug').empty();
}
$('#debug').append($('<pre/>').text(txt));
}
function canBeDropped(elem, item) {
var currentRow = $(item);
var ret = true;
$('tr', elem).not(currentRow).each(function() {
// We check all rows of the target element for one with the same ID.
// In indido this would check the email address, name, id or whatever.
// I'd suggest to store this information in data(), too, as it's the easiest
// way to access it here.
if($(this).data('id') == currentRow.data('id')) {
ret = false; // set return value for outer function
return false; // cancel the loop
}
});
return ret;
}
$('.sortblock tbody').sortable({
connectWith: '.sortblock tbody', // interconnect all sortable tables
placeholder: 'placeholder', // set a class for the placeholder row
handle: '.sort-handle', // require the user to use the sorting handle to move items
start: function(e, ui) { // triggered when sorting starts (i.e. when the user stargs dragging)
// so we have a valid placeholder row
ui.placeholder.html('<td></td>');
// mark all valid drop areas as targets
$('.sortblock').each(function() {
if(canBeDropped($('tbody', this), ui.item)) {
$(this).addClass('drop-target');
}
else {
$(this).addClass('no-drop-target');
}
});
},
stop: function(e, ui) { // triggered when sorting finished (cancelled or successfully sorted)
//remove drop target highlighting
$('.sortblock').removeClass('drop-target no-drop-target');
},
receive: function(e, ui) { // triggered when an element is being dropped
// check if we are a child of a drop target
if(!$(this).closest('.drop-target').length) {
$(ui.sender).sortable('cancel');
alert('You cannot...