Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery UI Droppable: How can I use different hoverClass values based on some logic?

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"
});
like image 409
musefan Avatar asked Mar 05 '13 14:03

musefan


3 Answers

$(".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/

like image 118
lucassp Avatar answered Sep 23 '22 18:09

lucassp


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
    }
});
like image 29
Matt Fletcher Avatar answered Sep 23 '22 18:09

Matt Fletcher


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.

like image 24
musefan Avatar answered Sep 20 '22 18:09

musefan