iam3yal
iam3yal

Reputation: 2339

jQuery drag and drop, the drop event doesn't fire when dropping an element on an area that was scrolled

I'm using jQuery UI for my drag and drop and everything is working pretty nicely the only problem I have is that when I'm scrolling and then I'm trying to drag an element and drop it in the scrolled area the element is reverted to its original position.

Just to clarify, by default it doesn't scroll right away when you dragging it out of the left section, only after you dropped it once then you can pick the element and scroll it left or down.

I posted an example at jsfiddle which demonstrates my problem.

$("#sidebar section span").draggable({
    cursor: "move",

    helper: "clone",

    revert: "invalid",

    //containment: "html",

    scroll: true
});

$("#main section").droppable({
    tolerance: 'fit',

    accept: "#sidebar section span",

    drop: function(e, ui)
    {
        console.log("Drop");

        var $draggedElement = ui.draggable;
        var $droppedArea = $(this);

        var droppedAreaLeft = $droppedArea.offset().left;
        var droppedAreaTop = $droppedArea.offset().top;

        $droppedArea.parent().css("overflow", "auto");

        var $draggableElement = $draggedElement.clone();

        $draggableElement.draggable({
            containment: [droppedAreaLeft, droppedAreaTop],

            scroll: true,

            scrollSpeed: 10,

            scrollSensitivity: 10
        });

        $droppedArea.append($draggableElement);

        $draggableElement.offset(ui.offset);
    },
});

Upvotes: 2

Views: 478

Answers (1)

iam3yal
iam3yal

Reputation: 2339

I've solved it by overriding the default function and added a new state to tolerance that supports scrolling.

Here is the code.

var _intersect = jQuery.ui.intersect;

jQuery.ui.intersect = function(draggable, droppable, toleranceMode) {

    if (!droppable.offset) {
        return false;
    }

    var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
        y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height,
        l = droppable.offset.left, r = l + droppable.proportions.width,
        t = droppable.offset.top, b = t + droppable.proportions.height;

    switch (toleranceMode) {
        case "scroll":  
            var overflowBottom = droppable.element.scrollParent().scrollTop();
            var overflowRight = droppable.element.scrollParent().scrollLeft();;

            x1 = x1 - overflowRight;
            y1 = y1 - overflowBottom;
            x2 = x2 - overflowRight;
            y2 = y2 - overflowBottom;

            return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
        default:
            return _intersect.apply(this, arguments);
        }
};

Upvotes: 2

Related Questions