I am using jQuery droppable (in conjunction with jQuery draggable) to allow the user to add rows to an HTML table by dragging items from a list and dropping them on the table.
This works well, however at present the logic is that when the user drag-drops on a table row the new row gets added below the row they dropped on.
It would be better if the new row’s add position was based on whether the user dropped in the upper or lower half of an existing row.
This is easy enough to calculate in the drop event, but I need to give UI feedback as the user drags (which I would do by means of two CSS classes droppable-above and droppable-below for example).
This doesn’t seem to be possible, as the over event only fires once; when the user initially drags over the droppable element.
Is it possible to get the over event to fire for every mouse move while the user is over a droppable element?
If so, then I’d be able to do this:
$("tr.droppable").droppable({
over: function(event, ui) {
if (/* mouse is in top half of row */) {
$(this).addClass("droppable-above").removeClass("droppable-below");
}
else {
$(this).removeClass("droppable-above").addClass("droppable-below");
}
},
out: function(event, ui) {
$(this).removeClass("droppable-above").removeClass("droppable-below");
},
drop: function(event, ui) {
$(this).removeClass("droppable-above").removeClass("droppable-below");
if (/* mouse is in top half of row */) {
// Add new row above the dropped row
}
else {
// Add new row below the dropped row
}
}
});
The CSS styles would be something like…
droppable-above { border-top: solid 3px Blue; }
droppable-below { border-bottom: solid 3px Blue; }
As you said,
over(like its counterpartout) is only raised once on the droppable. On the other hand, thedragevent of the draggable is raised every time the mouse moves, and seems appropriate for the task. There are, however, two problems with this strategy:dragis raised whether or not the draggable actually lies over a droppable,One way to solve both problems is to associate the droppable and the draggable in the
overhandler, using jQuery’s data() facility, and disassociate them in theoutanddrophandlers:Now that the draggable knows the droppable it’s lying over, we can update the element’s appearance in a
dragevent handler:The code that follows is a simple test case that demonstrates this solution (it basically fills the commented gaps above and refactors common patterns into helper functions). The droppable setup is a little more intricate than in the previous example, mainly because the newly created table rows have to be made droppable like their siblings.
You can see the results in this fiddle.
HTML:
CSS:
Javascript: