I am using the JQuery UI droppable library features, and I want to provide visual user feedback when they hover over a droppable target. For this I can easily use the hoverClass
option to specify which class to use when they have a draggable item hovering over.
But what I want to do is use a different hoverClass
value depending on some logic. Basically, there are a number of areas that are "droppable", and there is a number of items that can be dragged and dropped - however, not all items can be dropped on all areas. So I would like to have, for example, a green background if the drop is valid, and a red background if the drop is invalid.
How can this be done? I know what logic I want to use, but where can I add the logic. It obviously needs to be somewhere I can access the element being dragged, and the potential drop target element.
My simple code so far is as follows:
$(".DragItem").draggable({
revert: true,
helper: "clone"
});
$(".DropItem").droppable({
tolerance: "touch",
hoverClass: "DropTargetValid"
});
$(".DropItem").droppable({
tolerance: "touch",
hoverClass: "DropTargetValid",
over: function(event, ui) {
console.log(ui.draggable); // the draggable object
console.log($(this)); // the droppable object
}
});
This should do it. On over that event will be triggered on all .DropItem elements. You can find more about the available events API here: http://api.jqueryui.com/droppable/
I think your issue is trying to do it with the class itself, when droppable has its own hover event, called over
jQuery droppable API #over
So you'd want:
$(".DropItem").droppable({
tolerance: "touch",
over: function(event, ui) {
// ... logic goes here
}
});
The other answers are exactly what I was looking for. However, I want to go into a bit further detail here to give a better example of how to process the logic.
Lets say for example, with have some simple HTML as follows. This HTML basically has 4 draggable objects, and 4 possible drop targets:
<div style="margin-bottom:20px;">
<div data-id="1" class="DragItem">I am 1</div>
<div data-id="2" class="DragItem">I am 2</div>
<div data-id="3" class="DragItem">I am 3</div>
<div data-id="4" class="DragItem">I am 4</div>
</div>
<div>
<div data-id="123" class="DropItem">I accept 1, 2 and 3</div>
<div data-id="23" class="DropItem">I accept 2 and 3</div>
<div data-id="34" class="DropItem">I accept 3 and 4</div>
<div data-id="1234" class="DropItem">I accept all</div>
</div>
As can be seen, I have used data-*
attributes to store specific identifying values. The IDs on the DragItem identify the drag object, and the IDs on the DropItem contain all valid values.
The javascript that processes this logic, and then applies the correct classes is as follows:
$(".DragItem").draggable({
revert: true,
helper: "clone"
});
$(".DropItem").droppable({
tolerance: "touch",
over: function (event, ui) {
var dropItem = $(this);
var dragItem = $(ui.draggable);
var valid = String(dropItem.data("id")).indexOf(dragItem.data("id")) > -1;
if (valid) {
dropItem.addClass("DropTargetValid");
} else {
dropItem.addClass("DropTargetInvalid");
}
},
out: function (event, ui) {
var dropItem = $(this);
dropItem.removeClass("DropTargetValid");
dropItem.removeClass("DropTargetInvalid");
},
deactivate: function (event, ui) {
var dropItem = $(this);
dropItem.removeClass("DropTargetValid");
dropItem.removeClass("DropTargetInvalid");
}
});
As can be seen, I am doing a simple "does string contain" logic check. This is fine for small numbers but if there is ever a need to do more than 9 object we would need a more reliable string in the DropItem data-id
value.
I also use the out
and deactivate
events to clear up the applied classes. In this example I duplicate the code, but this could easily be replaced with a single function used by both events.
Finally, the moment you have all been waiting for, here is a working example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With