The idea is pretty simple and it almost works. There are two tables and the user has the option of dragging rows between the two tables. When a row is dragged from table1 to table2, ajax is used in order to update the database with the data that is removed from table1, added to table2, and to re-display both of the tables with the new data. The same thing works if information is dragged from table2 to table1.
You can see a sample of the code here.
Here is an excerpt of the Javascript code for one of the tables:
var startTable = "table1";
var $tabs=$("#" + startTable);
$( "tbody.connectedSortable")
.sortable({
connectWith: ".connectedSortable",
items: "> tr:not(:first)",
appendTo: $tabs,
helper:"clone",
cursor:"move",
zIndex: 999990
})
.disableSelection()
;
$($tabs).droppable({
accept: ".connectedSortable tr",
hoverClass: "ui-state-hover",
drop:function(event, ui){
var start= ui.draggable.attr("id");
var desTable = $(this).attr("id");
if(start != desTable){
alert("The ajax should be called");
}
return false;
}
});
It works perfectly except for just one case. If a row is being dragged from Table1 to Table2, it creates a slot to show where the row will be inserted when the row is let go. In other words, if a user drags a row from Table1 to the last element of Table2, it creates an open place-holder (under the last row in Table2) to depict where the row will go when let go. There is one problem with this. If the place-holder is created but the row is then dragged outside of the table and let go, the row still goes to the place-holder but the draggable property is never called.
What I would like to happen is if a place-holder is created, no matter where the row is let go, it will go to the place-holder and call the droppable code that corresponds to the table it was dropped in. If no place-holder is present, the row should go back to where it was dragged from and nothing should happen.
Every example I've tried that drags rows between two tables has the same problem. Do you guys have any way to call the droppable code even if the row is being dropped outside of the table? Or maybe there is a better way to call ajax rather than when the row is dropped on the table? Any insight would be greatly appreciated.
For triggering an ajax request when a row is dropped from one table to another you can use the receive event of
sortable
widget.(emphasis mine)
Updated Fiddle (Partial result, See the below snippet for final demo)
Inside the receive callback, you can access the dropped row using the
item
property of second argument (ui.item
).If the receive event callback is triggered, it means
ui.item
has been added tothis
table ($(this).closest("table.mytable")
) and removed from the other table ($("table.mytable").not($(this).closest("table.mytable"))
). You can then trigger the ajax request(s) accordingly.By doing it this way, you don't have to manually check whether drop happened within the same table or not (You'll have to do this if you're using update event as someone suggested).
At the moment, you're unnecessarily initializing the sortable twice with:
and
The selector
tbody.connectedSortable
is applicable to both tables, hence it'll simply override the previous initialization, As the result, the clone helper will be always appended to the second table ($tabs2
). It is probably not what you want - from the looks of it you're initializing twice just for appending the clone to respective parent. The default value ofappendTo
option is"parent"
, just removing it from initialization will do the job.Also, it is a good idea to move the header rows from
<tbody>
into<thead>
element so that you can avoid specifyingitems: "> tr:not(:first)"
: it is more semantic as well as slightly better for performance since jQuery UI doesn't have to search for invalid items if that option is not specified.Finally, you've duplicate
id
's which is invalid. For grouping a set of elements, use a common class instead.Side note: I've combined the similar CSS classes