Search code examples
javascriptjqueryhtmljquery-ui-draggablejquery-droppable

Jquery how to specify which droppable should be used with nested droppable elements


I have a small problem which i can't seem to solve myself. Look at this fiddle:JSfiddle

This is a basic example of the problem I have. I have a large div which is a droppable area. Inside this droppable area are multiple other droppable areas.

The inner droppable area should walk trough its code when the element is dropped. Instead the code from the outer div seems to run. Am i doing something wrong? The area around the divs should stay this way because elements can be placed here (not officially dropped).

I hope my question is clear enough, but I think the fiddler speaks for itself.

P.S. - resizing in this example isn't functioning but is functioning in my development environment.


Rusty and Mark, Thank you for your replies.

I'm sorry for the confusing resizer. I just removed that from the code. New Fiddler

Just to clarify things. The box div is a container which has multiple images in it. I am trying to achieve the following: http://postimage.org/image/qwhtik04f/ The grey dotted boxes are the dropbox2 div from my example. The space around those drop boxes are dropbox div.

The space with the board is the only place where images may be dropped without anything happening. The dragged images can snap back to the dropbox2 divs. If the images are dragged onto the dropbox div, the images should revert.


Solution

  • Your code has this for the outer <div>:

    $("#dropbox").droppable({
        drop: function(event, ui) {
           ui.draggable.draggable( 'option', 'revert', true );
        }
    });
    

    This says to set the revert option to true when you drag into the outer <div>. However, when you drop in the smaller <div>, the option is still set to true. All you need to do is change the revert value on your draggable element after a successful drop in your inner <div>:

    $("#dropbox2").droppable({
        drop: function(event, ui) {
            ui.draggable.position( { of: $(this), my: 'center', at: 'center' } );
            // Add this line
            ui.draggable.draggable( 'option', 'revert', false );
        }
    }); 
    

    Update:

    Mark pointed out that my solution doesn't stop the propagation of the event to the parent container. As his answer shows, you need to add greedy: true in your initial options. The jQuery documentation says:

    If true, will prevent event propagation on nested droppables.

    That sounds like what you're looking for. You still need to change the revert property on your draggable, since greedy is only set on your droppables and won't affect your draggable reactions.