Search code examples
jqueryhtmlcssjquery-ui-draggablejquery-ui-droppable

Overlapping droppables in scrolling divs


I have two panels of draggable and droppable elements. Both have long lists and I have to constrain the sizes of panels and make them scrollable. Here is the jsfiddle with sample code. http://jsfiddle.net/hemant_sathe/sYhYK/48/

Embedding the CSS here just because I need some code to embed jsfiddle link

.panel{
height: 150px;
overflow: auto;
margin: 0 0 20px 0;
border: 1px solid red;
}

My issue is if I drag item from top list and drop it on the list below, the drop event is captured by the list from top panel first and then by the bottom panel. This does not happen when dragging item from lower list and dropping on to upper one.

My understanding is that the HTML from top panel is just hidden by the scrollable panel but the javascript still captures events on the same DOM. This behavior does not change even if I make the droppable greedy as the event is captured by the top list. Setting Z-index also did not help me either.

One of the option is to check if the droppable is visible in view port but in my actual project, I am using knockout binding and adding this functionality will make my code difficult to manage.

Is there any way to solve this by use of HTML, CSS or some quick JS function?

Thanks in advance.


Solution

  • I solved this by checking if the element at the point where I am dropping is the same element or child of element that is capturing the drop. Here is the code that checks this

        drop: function (event, ui) {
                //Due to scrollable divs, the schedule drag drop may get wrongly captured by hidden elements
                //We ensure that the element at drop location is the same element or contained element 
                //which captures the drop
                var dropElement = document.elementFromPoint(event.clientX, event.clientY);
    
                //dropLocation is the droppable element on which we drop
                //The point where we drop must be on dropLocation or its child element
                //When the dropLocation is not visible due to scrollable div, second
                //event which is captured by correct element is executed.  
                if (dropLocation == $(dropElement) ||
                        dropLocation.find($(dropElement)).length > 0) {
    
                // code to execute on successful drop
                }
            }
    

    Here is the solution jsfiddle: http://jsfiddle.net/hemant_sathe/umwHJ/8/