При клонировании перетаскиваемого объекта в пользовательском интерфейсе jQuery, как вы можете перенести данные и события в новый элемент?

У меня есть перетаскиваемый элемент с набором helper: 'clone', но когда он клонирует элемент, ни один из data() или событий не сохраняется в новом элементе.

Я пробовал несколько способов повторно привязать data(), но я не могу выбрать новый элемент, а также старый элемент в том же самом выражении.

Например, я могу выбрать начальный элемент в перетаскиваемом событии stop():

$blah.draggable({
    helper: 'clone',
    stop: function(ev, ui) {
        var oldData = $(ev.target).data('blah');
    }
});

И я также могу получить новый элемент в событии droppable drop():

$blah.droppable({
    drop : function(ev, ui) {
        var $newElement = ui.draggable;
    }
});

Но я не могу понять, как получить оба в одном и том же случае.

Что бы я хотел сделать, так это передача данных, например:

$newElement.data('blah', $oldElement.data('blah'));

Или иначе сделайте данные постоянными, как вы можете с помощью $blah.clone(true);

Ответ 1

Чтобы получить доступ к данным исходного элемента в drop, вы можете использовать ui.draggable.context. В приведенном ниже примере контекст будет ссылаться на исходный элемент перетаскивания, и у вас есть доступ ко всему его содержимому. Draggable ссылается на новый элемент, который отбрасывается.

$("#droppable").droppable({
    drop: function(ev, ui) {        
        console.log(ui);
        console.log(ui.draggable.context);
        console.log($(ui.draggable.context).data('pic'));
    }
});

Ответ 2

Я не слишком много работал с droppable, но не мог бы вы просто сделать что-то вроде этого?

$(".draggable").draggable({
    helper: 'clone'
});

$("#droppable").droppable({
    drop: function(ev, ui) {
        $(this).append(ui.draggable.clone(true));
    }
});

Кажется, работает, если там что-то не хватает:

http://jsfiddle.net/hasrq/

Ответ 3

Оказывается, проблема была сортируемой, а не draggable/droppable (позже я добавлял сортировку, но понял, что это не часть проблемы здесь, поэтому я оставил ее из исходного вопроса).

В итоге я использовал некоторую комбинацию решения @kingjiv выше, а также не самый лучший хак, но, по крайней мере, он работает:

$blah.sortable({
    receive: function(ev, ui) {
        // setting a global variable here
        MyGlobals.cloneCache = ui.item.clone(true);
    },
    stop: function(ev, ui) {
        $(ui.item).replaceWith(MyGlobals.cloneCache);
    }
});

Идея состоит в том, что вы сначала клонируете исходный элемент в событии receive(), кешируете это в переменной, а затем заменяете элемент на событие stop().

Вид уродливый, но по крайней мере он работает.

Ответ 4

ui.item относится к перетаскиваемому элементу. Когда объект перетаскивается, нет встроенного способа доступа к целевому элементу из функции receive. Однако есть немного хакерский способ, как это сделать:

$blah.sortable({
    receive: function (ev, ui) {
        var $target = $(this).data().sortable.currentItem;
        var $source = $(ui.sender);
        // now you can copy data from source to target
        $target.data('data-item', $source.data('data-item')); 
    } 
});