Search code examples
htmljquerycssdrag-and-dropjquery-ui-draggable

JQuery - Unlink draggable element from its scrollable area


I am implementing a drag-drop functionality where there is a scrollable div container (like a bottom bar) containing the elements (divs) that must be dragged to an area above the original container.

drag unliked from scrollable area

However, when I drag and drop any of the elements in the drop area, this element remains "associated" with the scrolling area, because if I scroll left or right the bottom bar, the element follows and changes its position in the drop area. As if it were still on the bottom bar.

JQuery

$('#home .scroll_carrossel .nav-container .personBtn').draggable({
    distance: 0,        
    drag: function(e, ui) {},
    revert: function(dropped) {
        var dropped = dropped && dropped[0].id == "dropped";    
        if(!dropped) {
            for(var i=0; i < qtdObj; i++) {
                posicao(this,'obj'+(i+1), 0,  0 );
                if(i > 0){
                    posicao(this,'obj'+(i+1), 0,  i*56.3 ); 
                }
            }     
        }
        return !dropped;
    } 
});

$('#home .droppable').droppable({
    accept: '.personBtn',
    tolerance: 'intersect',         
    over: function(event, ui) {
        var dragId = $(ui.draggable).attr("id");
        $('.personBtn.ui-draggable-dragging').removeClass('backing').addClass('dropping').css("z-index", 10);
    },
    out: function(event, ui) {
        var dragId = $(ui.draggable).attr("id");
        $('.personBtn.ui-draggable-dragging').removeClass('dropping').addClass('backing');
    },
    drop: function(event, ui) {
        $('.personBtn.ui-draggable-dragging').addClass('dropping').css("z-index", 0);           
    }
}); 

function posicao(tag, objeto, top, left){
    if($(tag).attr('id') == objeto){
        $(tag).data("uiDraggable").originalPosition = {
            top: top, left: left
        }
    }
}

HTML:

<section id='home'>
    <div class="droppable" id="dropped"></div>
    <div id="lefty"></div>
    <div class='scroll_carrossel'>
        <div class="nav-container">
            <div class="personBtn" id="obj1" ></div>
            <div class="personBtn" id="obj2" ></div>
            <div class="personBtn" id="obj3" ></div>
            <div class="personBtn" id="obj4" ></div>
            ...
        </div>
    </div>
    <div id="righty"></div>                     
</section>

CSS:

#home .droppable {
    position: absolute;
    width: 846px;
    height: 400px;
    top: 27px;
  }

#home .scroll_carrossel {
    width: 100%;
    height: 60px;
    background-color: #FFF;
    position: absolute;
    bottom: 15px;
    display: flex;
    overflow: visible;
}

#home .scroll_carrossel .nav-container{
    width: 3384px;
    height: 60px;
    position: absolute;
    left: 0;
    top: 0; 
}

#home .scroll_carrossel .nav-container .personBtn{
    position: absolute;
    width: 240px;
    height: 240px;
    margin: 5px;
    display: inline-block;
}

/* for each element */
#home .scroll_carrossel .nav-container #obj1.personBtn  {
    background-image: url(img/objetos/obj1.png);
    background-size: contain; 
    transform-origin: top left; 
    transform: scale(0.2);
} 
/* and so on... */

#home .scroll_carrossel .nav-container .personBtn.dropping{
    -webkit-animation: dropping 0.5s ease-out forwards;
    animation: dropping 0.5s ease-out forwards;
    transform-origin: center center;
}
@-webkit-keyframes dropping {   
    100%{transform: scale(1);}
}
@keyframes dropping {   
    100%{transform: scale(1);}
}

#home .scroll_carrossel .nav-container .personBtn.backing{
    -webkit-animation: backing 0.5s ease-out forwards;
    animation: backing 0.5s ease-out forwards;
    transform-origin: top left;
}
@-webkit-keyframes backing {
    100%{transform: scale(0.17);}
}
@keyframes backing {
    100%{transform: scale(0.17);}
}

How is it possible to scroll the bottom bar (and all elements positioned inside it) without interfering with the position of the element already dropped in the area above?


Solution

  • You need to attach your draggable element to your droppable container:

    drop: function(event, ui) {
        $('.personBtn.ui-draggable-dragging').addClass('dropping').css("z-index", 0);  
        $(this).append(ui);
    }