Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery UI draggable: clone if Ctrl pressed down

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);
        }
    });
like image 299
Mad Scientist Avatar asked Aug 27 '10 11:08

Mad Scientist


1 Answers

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.

like image 190
Nick Craver Avatar answered Oct 02 '22 09:10

Nick Craver