Arris
Arris

Reputation: 31

Detect multiple elements below dragged object? Javascript/Jquery

I have a button that dinamically creates an object and makes it "draggable" with the following code using jquery:

createNewDiv(divId); <--local function that creates a new div with id=divId
$("#"+divId).draggable();

which makes the element with element Id = divId draggable (thanks to jquery libs), so any newly created element can be dragged and dropped anywhere in the page

Now, suppose that I create element A, B and C, all of them draggable, and I drag n' drop one above another (so C stays "over" B, and B stays "over" A, just like paper sheets stacked one above the other)

Is there any way to detect which elements are below each one of them? For example, when hovering over C it would return an "element B and element A are below.." (both of them) or when hovering B it would return "element A is below"?

I've investigated a few methods like elementFromPoint() or the .droppable() method from jquery, but I can't seem to return --multiple elements-- below any other (for example C to return both A and B below it)

Another way that I could imagine with this code is to override the .droppable() and invoke it recursively, but currently I don't see how. For example, when:

a) Dropping A, nothing gets displayed (no element below it)

b) Dropping B over A - "B on {A}" displayed

c) Dropping C over B - "C on {B,A}" (C finds B, which B finds A)

jQuery or native Javascript would be greatly appreciated

Upvotes: 3

Views: 1163

Answers (1)

buzzedword
buzzedword

Reputation: 3168

I'd imagine the best way to do this would be to do something like:

var bufferInteger = 0, dragParent = $( container ), dragChildren = {};
(function layerCalculation(){
    dragParent.find('.draggable').each(function(index, val){
        var child = $(val), 
          childOffset = {
            top    : child.offset().top,
            left   : child.offset().left,
            width  : child.width(),
            zIndex : child.css('z-index')
          };
        dragChildren[child.attr('id')].top = childOffset.top;
        dragChildren[child.attr('id')].left = childOffset.left;
        dragChildren[child.attr('id')].width = childOffset.width;
        dragChildren[child.attr('id')].zIndex = childOffset.zIndex;
    });
}());

function detectHover(ui){
    var currentlyOver,
        uiElement = ui.helper[0],
        underStacked = dragChildren, 
        draggedItem = {
        id     : uiElement.id,
        offset : {
            left : uiElement.offsetLeft,
            top  : uiElement.offsetTop
        }
    };
    underStacked.splice(understacked.indexOf(draggedItem.id), 1);

    for (var i in underStacked){
        if ((underStacked[i].left <= draggedItem.offsetLeft <= (underStacked[i].left - - underStacked[i].width)) {
            currentlyOver = underStacked.id;
        } else if (...) {
            // do some logic here to calculate draggedItem.offsetLeft + draggedItem.width
        }
    }
    if (typeof currentlyOver !== 'undefined'){
        return currentlyOver;
    } else {
        return false;
    }
}
$('.draggable').bind({
    dragstart : function(){
        layerCalculation();
    },
    dragend : function(){
        layerCalculation();
    },
    drag : function(event, ui){
        bufferInteger++;
        if (bufferInteger > 9){
            bufferInteger = 0;
            detectHover(ui);
            ...
            // do something with return ID here.
        }
    }
});

Upvotes: 1

Related Questions