7

I have a droppable unordered list named <ul class="droppable">. Inside the unordered list I have dynamicly generated list items named <li class="placeholder"></li>, which are also droppable.

When dropping a draggable item between a placeholder, all works fine. But when dropping a draggable item on the <li class="placeholder"></li> itself, the draggable item gets appended to the placeholder and the unordered list.

So I get a double clone of it.

Here's a jsfiddle to have a visual example. I'm aware that it is logical that I get a double clone on my page, but I don't know how to disable it...

Any help is greatly appreciated!

UPDATE: If you drag a draggable item verticaly over a droppable element, they append automatically? How is that possible?

Jeroen Bellemans
  • 2,049
  • 2
  • 25
  • 42
  • Already answered here [droppable in droppable](http://stackoverflow.com/questions/5504888/droppable-in-droppable). Use the greedy option. – Martin Verner Jul 20 '15 at 12:12
  • It must accept both. It should sort & append the reserved placeholders, but when hovering a placeholder it should append to the placeholder itself. – Jeroen Bellemans Jul 20 '15 at 13:33
  • In response to your update, comment out your `//sorting();` function and you will see that they no longer append automatically. Something that happens when you combine your sorting and dropping functions. – Trevor Jul 23 '15 at 20:42
  • Thanks for your reply. Indeed it has something do to with the `receive` event from sortable and the `drop` event from droppable. It's a bug when one uses them together. http://stackoverflow.com/questions/18664641/jquery-ui-drop-event-of-droppable-widget-firing-twice – Jeroen Bellemans Jul 24 '15 at 07:28

2 Answers2

2

One approach you could try to solve this would be to move all your behaviors to your sortable and use droppable only to make a switch to determine the behavior you need. That way, you can handle everything at one place, which should resolve some of the unwanted effects of having both sortable and droppable on the same elements. Like this:

In your droppable you set the switch on over and out, and set the objects you need.

 $("li.placeholder").droppable({

                accept: "li.to-drag",
                hoverClass: "correct",
                activeClass: "active",
                revert: false,
                tolerance: "pointer",
                over: function (e, ui) {
                   curDrag = ui.draggable;
                   curTarget = e.target;
                                        curThis = $(this);
                    overSortable = true;
                },
                out: function (e, ui) {
                    overSortable = false;
                },

                drop: function (event, ui) {

                }

            });

Then, in beforeStop event of sortable, you check if the variable overSortable is true or not and set the behaviors there. All that refers to ui.draggable, this, and event.target will need to be replaced by the objects you set in droppable. An event better way would be to make a function handling all these behaviors and pass these as arguments.

beforeStop: function (e, ui) {
                if (overSortable) {
                   curDrag.addClass('placeholder');
                   var dragging = curDrag.find("img").remove();

                   curThis.append(dragging).addClass("dropped");
                   curThis.droppable('disable');

                    var day = curDrag.attr('data-id');
                    var index = $(curTarget).index();

                    //...

                } else {
                    ui.item.addClass('placeholder')
                }

There are still adjusments to make, it's not completely clear what exactly should happen and when, but this can make it easier to work instead of trying to manage multiple events being fired when you drop an element, you only manage one.

http://jsfiddle.net/ts290vth/4/

Julien Grégoire
  • 16,864
  • 4
  • 32
  • 57
1

Managed to get it working for you:

function dropping () {

        $("li.placeholder").droppable({

            accept: "li.to-drag",
            hoverClass: "correct",
            activeClass: "active",
            revert: false,
            tolerance: "pointer",

            drop: function (event, ui) {

                var dragging = ui.draggable.find("img");

                $(this).append(dragging).addClass("dropped");
                $(this).droppable('disable');

                var day = $(ui.draggable).attr('data-id');
                var index = $(event.target).index();

                $(this).attr("data-id", day);
                $(this).attr("date-order", index);
                $(this).addClass("drop-"+ index);
                $(this).attr("data-content", "");

NOTICE: the var dragging = ui.draggable.find("img"); this line was making you duplicated copies at drag and drop so you just had to remove the clone();.

it created clones of your dragged items at dest.

Now Notice this:

$("#dropzone").droppable({

        accept: "li.to-drag",
        revert: false,
        tolerance: "pointer",

        drop: function (event, ui) {

            $(this).append(dragging);
            //$("li.to-drag").addClass("placeholder");
            $(this).droppable('disable');

        }

    });

}

Something with the placeholder class is causing you troubles.

Hope this helps.

Barr J
  • 10,636
  • 1
  • 28
  • 46