cbcrc / knockout-dragula

Simple binding for Knockout.js to add drag and drop functionality to observableArrays using dragula
13 stars 6 forks source link

Handle cloned event #11

Open laurentlbm-rc opened 8 years ago

laurentlbm-rc commented 8 years ago

When the copy option of dragula is enabled, the HTML is copied instead of moved. We need to handle this behaviour and copy the view model.

We can bind ourselves to the cloned event.

HeinzLm commented 7 years ago

Hi, thanks for the binding!

I implemented it pretty simply by adding drake.on('cloned', onCloned); to the registerEvents(drake) function.

In there i just save the clone of the original and set a flag:

var cloneBackup, copying;

function onCloned(clone, original, type) {
    if (type === 'copy') {
        copying = true;
        cloneBackup = original;
    }
}

In the onDrop handler i then get the item from the backup if copying is true:

if (copying) {
     item = _ko['default'].dataFor(cloneBackup);
}

And then add a copy to the sourceItems:

sourceItems.splice(sourceIndex, 1);
if (copying) {
    var koCopy = ko.mapping.fromJS(ko.mapping.toJS(item));
    sourceItems.push(koCopy);
    copying = false;
}
targetItems.splice(targetIndex, 0, item);

As i use the ko.mapping plugin anyways it is no added dependency for me.

With removeOnSpill: true i had to put an if (container != null) check in the onCancel(el, container) as when copy is true cancel gets called and not the remove.

My binding would look something like that:

<div style="-ms-touch-action: none; touch-action: none;" data-bind="attr: { id: 'divEmptySpace' }, 
    dragula: { data: spaces, group: 'spaces',  afterDrop: $root.afterDrop,
        copy: function (el, source) {
            return source.id === 'divEmptySpace';
        },
        accepts: function (el, target) {
            return target.id !== 'divEmptySpace';
        },
        removeOnSpill: true 
    }"
>