Deepankar
Deepankar

Reputation: 48

Over event isn't propagated if nested droppable doesn't accept draggable under a certain scenario

The steps below are applicable to the jsFiddle shared below.

Steps:

  1. Click on and drag Draggable 1 onto the inner droppable of Droppable 3. Continue to hold Draggable 1, do not release it.
  2. Note that when Draggable 1 is on the inner droppable and the pointer is fully over the area of Droppable 3, the outer Droppable 3 is highlighted, which is expected.
  3. Move Draggable 1 beyond the bounds of Droppable 3 and release it so that it's resting entirely in whitespace.
  4. Click and drag Draggable 2. You only have to drag it to some random whitespace spot, not on a droppable.
  5. Release Draggable 2.
  6. Grab Draggable 1 again and drag it onto the inner droppable of Draggable 3. Continue to hold Draggable 1, do not release it.
  7. When Draggable 1 is on the inner droppable and the pointer is fully over the area of Droppable 3, take a note of the state of the outer Droppable 3 container.

Expected results:

Actual results:

Notes:

Related Question:

I'm asking this question because it seems somewhat related to the following StackOverflow question, but my scenario is slightly different. Perhaps it has the same root cause, but there might be a different workaround?

jsFiddle:

https://jsfiddle.net/deepankarj/60zz9zgb/

$(function() {
    $("#draggable, #draggable2").draggable({
        cursor: "move",
        cursorAt: {
            top: 0,
            left: 0
        },
    });

    function logEventId(prefix, event) {
        console.log(prefix + ": " + event.target.id); 
    }
    function createLogEventIdFunction(handlerName) {
        return function(event, ui) {
            logEventId(handlerName, event);
        }
    }

    $("#droppable, #droppable-inner").droppable({
        activeClass: "ui-state-hover",
        hoverClass: "ui-state-active",
        tolerance: "pointer",
        over: createLogEventIdFunction("over"),
        out: createLogEventIdFunction("out"),
        drop: function(event, ui) {
            logEventId("drop", event);
            $(this)
                .addClass("ui-state-highlight")
                .find("> p")
                .html("Dropped!");
            return false;
        }
    });

    function decorateWithDroppable(selector, greedy, canAccept, over) {
        canAccept = !!canAccept ? canAccept : function(element) {
            console.log("canAccept: this: " + $(this).attr("id") + ", el: " + element.attr("id") + ", result: true");
            return true;
        };

        over = !!over ? over : createLogEventIdFunction("over");

        $(selector).droppable({
            greedy: greedy,
            activeClass: "ui-state-hover",
            hoverClass: "ui-state-active",
            tolerance: "pointer",
            accept: canAccept,
            over: over,
            out: createLogEventIdFunction("out"),
            drop: function(event, ui) {
                logEventId("drop", event);
                $(this)
                    .addClass("ui-state-highlight")
                    .find("> p")
                    .html("Dropped!");
            }
        });
    };

    decorateWithDroppable("#droppable2, #droppable2-inner", true);
    decorateWithDroppable("#droppable3", true);
    decorateWithDroppable("#droppable3-inner", true, function canAccept(element) {
        console.log("canAccept: this: " + $(this).attr("id") + ", el: " + element.attr("id") + ", result: " + (element.attr("id") !== "draggable"));    
        return (element.attr("id") !== "draggable");
    });

});

Upvotes: 1

Views: 132

Answers (1)

Santosh Pradhan
Santosh Pradhan

Reputation: 149

Setting refreshPositions to true when initializing draggable works for me. Here is the sample code.

jQuery().draggable({
    ....    
    refreshPositions: true
    ....
});

Upvotes: 0

Related Questions