0

I'm using this knockout binding to add html5 drag and drop to my application.

https://github.com/bramstein/knockout.dragdrop

I have two observable arrays with items that can be dragged between them.

On page load all the items in both lists are draggable and work as expected.

The problem occurs when I try to drag items back to their original list, the drag and drop stops working.

As you can see from my console.log, I have dragged and held the element for a few seconds and then dropped it into list 2.

When I try and drag that same element back to list 1, the drag start and drag end triggers instantly.

  • dragStart - 13:24:54
  • dragEnd - 13:24:56
  • dragStart - 13:25:0
  • dragEnd - 13:25:0

Below is my data-bind for list 1

    <ul data-bind="
        dropzone: { name: 'unassigned', drop: $root.DropUnassignedStandard }">

        <!-- ko foreach: DupeStandards -->
            <li data-bind="text: Name, 
                dragzone: { name: 'assigned', dragStart: $root.onStart, dragEnd: $root.onEnd }" draggable="true" />
        <!-- /ko -->
    </ul>

Below is my data bind for list 2

<div data-bind="
    dropzone: { name: 'assigned', drop: $root.DropAssignedStandard }">

    <ul>
        <!-- ko foreach: UnassignedDupeStandards -->             
        <li data-bind="text: Name, 
            dragzone: { name: 'unassigned', dragStart: $root.onStart, dragEnd: $root.onEnd }" draggable="true" />     
         <!-- /ko -->
    </ul>
</div>

Below is my onStart function

self.onStart = function (data) {

    var currentDate = new Date();
    var datetime = currentDate.getHours() + ":"
        + currentDate.getMinutes() + ":"
        + currentDate.getSeconds();

    console.log('dragStart - ' + datetime);
}

Below is my onEnd function

self.onEnd = function (data) {

    var currentDate = new Date();
    var datetime = currentDate.getHours() + ":"
        + currentDate.getMinutes() + ":"
        + currentDate.getSeconds();

    console.log('dragEnd - ' + datetime);
}

Below is the function to move items from list 1 to list 2

self.DropAssignedStandard = function (droppedStandard) {

    self.UnassignedDupeStandards.push(droppedStandard);

    var user = ko.utils.arrayFirst(self.Users(),
        function (user) {
            return ko.utils.arrayFirst(user.DupeStandards(),
                function (ds) {
                    return ds.DupeStandardID === droppedStandard.DupeStandardID;
                });
        });

    user.RemoveStandard(droppedStandard);
}

Below is the function to move items from list 2 to list 1

self.DropUnassignedStandard = function (droppedStandard, user) {
    user.AddStandard(droppedStandard);
    self.UnassignedDupeStandards.remove(droppedStandard);
}

Any help is appreciated, thanks.

SkelDave
  • 1,176
  • 2
  • 9
  • 23
  • I've used that library before and found it lacking. I would suggest checking this one out in it's place. https://github.com/rniemeyer/knockout-sortable | http://jsfiddle.net/rniemeyer/Jr2rE/ It's a bit more robust with it's events and what have you. – Budhead2004 Oct 18 '17 at 16:07

2 Answers2

1

Turns out it is a bug with chrome.

When modifying the DOM on dragstart it apparently breaks html5 drag and drop functionality.

Thanks to the other answers.

dragend, dragenter, and dragleave firing off immediately when I drag

SkelDave
  • 1,176
  • 2
  • 9
  • 23
0

Are you also seeing the error "user.AddStandard is not a function" in your console? I think the problem is the knockout context for your drop event.

<ul data-bind="
    dropzone: { name: 'unassigned', drop: $root.DropUnassignedStandard }">

In the DropUnassignedStandard function it appears your assumption was that the second argument would be the user.

self.DropUnassignedStandard = function (droppedStandard, user) {
    user.AddStandard(droppedStandard);
    self.UnassignedDupeStandards.remove(droppedStandard);
}

Unfortunately because the data-bind is attached outside of the foreach the second argument is the root view-model instead, and user.AddStandard will error. You'll need a different way to determine which user the item belongs to. Perhaps similar to what you have in the DropAssignedStandard function.

Jason Spake
  • 4,293
  • 2
  • 14
  • 22