views:

41

answers:

1

I have a list of draggable table cells that can be dropped onto a second table. They are set to clone, as the original table should remain unchanged if items are dragged from it.

Now I want to be able to move the dropped elements inside the second table from cell to cell. But if the Control key is pressed while dragging an element inside the second table the element should be cloned. Now I don't know how to elegantly achieve this last part.

My code so far, only the clone on Ctrl part is missing:

$(".drag_clone").draggable({helper: "clone"});
$(".draggable").draggable({revert: "invalid"});
$(".droppable").droppable(
    {
        drop: function(event, ui) {
            if (ui.draggable.hasClass("draggable")) {
                ui.draggable.remove();
            }
            $('<div class="draggable"></div>').text(ui.draggable.text()).draggable({revert: "invalid"}).appendTo(this);
        }
    });

The behaviour I'd like to achive is that if an element is dragged to another cell of the table, it should be moved there. If the element is dragged while the Ctrl key is pressed or if it is one of several predefined elements that should always be cloned, a copy of the element should be created and inserted into the target cell.

In the code I've pasted here I'm creating a new element that is then appended to the droppable. This works fine for clone draggables, but with non-clone draggables the original draggable remains, so I end up duplicating it.

If I instead just append the draggable to the target droppable, the clone draggable is removed from it original place.

Edit: I've found the problem, I was using ui.draggable, which refers to the original draggable, not ui.helper which refers to the cloned one. I add the final, working code here as a reference:

$(".drag_clone").draggable({helper: "clone"});
$(".draggable").draggable({revert: "invalid"});
$(".droppable").droppable(
    {
        hoverClass: 'ui-state-hover',
        drop: function(event, ui) {
            ui.helper.remove()
            $('<div class="draggable"></div>').text(ui.draggable.text()).mousedown(function(event) 
                {$(this).draggable('option', {
                         helper : event.ctrlKey ? 'clone' : 'original' });
                         }).draggable({ revert: "invalid" }).appendTo(this);
        }
    });
+4  A: 

You can do it by attaching a mousedown handler before the .draggable() call, like this:

$(".draggable").mousedown(function(event) {
  $(this).draggable('option', { helper : event.ctrlKey ? 'clone' : 'original'});
}).draggable({ revert: "invalid" });

You can see it in action here, since the widget also works on mousedown, we just want to attach an event handler before the widget's handler, since event handlers run in the order bound, so all we're doing is setting the helper option just before the drag starts.

Nick Craver
Thanks, this works fine for enabling clone mode. But now I have the problem that when I'm removing the draggable this also deletes the cloning draggable. I can't seem to find a way to distinguish between a normal draggable and a clone draggable.
Fabian
@Fabian - I'm not sure exactly what behavior you're after, can you explain a little more what should happen when dropping a cloned vs a non-cloned?
Nick Craver
I've tried to explain better, what I'm looking for in my original question.
Fabian
I've solved the problem, I used ui.draggable where I should have used ui.helper.
Fabian