Search code examples
javascriptjquerytwitter-bootstrapdrag-and-dropinteract.js

Cannot get interact.js drag & drop interactions to work with Boostrap elements


I'm attempting to get interact.js to work with Bootstrap list items. I have a very simple setup, but unfortunately I can't get it to work.

HTML (div containing two Bootstrap panels - one with some draggable list items, and another with two dropzones):

<div id="visualizer-panel">
    <div class="leftStuff panel">
        <div class="panel-heading">
            <h4 class="panel-title">Draggables</h4>
        </div>
        <div class="panel-body">
            <ul class="list-group">
                <li class="list-group-item draggable">asdf</li>
                <li class="list-group-item draggable">bbq</li>
            </ul>
        </div>
    </div>
    <div class="rightStuff panel">
        <div class="panel-heading">
            <h4 class="panel-title">Drop Areas</h4>
        </div>
        <div class="panel-body">
            <div class="dropzone">drop stuff here</div>
            <div class="dropzone">drop more stuff here</div>
        </div>
    </div>
</div>

CSS:

#visualizer-panel .leftStuff {
    float: left;
}
#visualizer-panel .rightStuff {
    float: right;
}

/* Visual cursor hint for draggable */
#visualizer-panel .draggable:hover {
    cursor: move;
}

/* Drag & Drop */
#visualizer-panel .draggable {
    -webkit-transform: translate(0px, 0px);
    transform: translate(0px, 0px);
}
#visualizer-panel .drop-active { border-color: red; }
#visualizer-panel .drag-drop.can-drop { background-color: #4e4; }
#visualizer-panel .drop-target {  background-color: #29e;  }

And Javascript:

// Initialize Interact.js Drag & Drop
interact('.draggable').draggable({
    inertia: true,
    restrict: {
      restriction: "#visualizer-panel",
      endOnly: true,
      elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
    },
    onend: function(event) {
        console.log(event);
    }
});

interact('.dropzone').dropzone({
    accept: '.draggable',
    overlap: 0.01,

    // add / remove dropzone feedback
    ondropactivate: function (event) {
        event.target.classList.add('drop-active');
    },
    ondropdeactivate: function (event) {
        event.target.classList.remove('drop-active');
    },

    // add / remove dropzone feedback
    ondragenter: function (event) {
        var draggableElement = event.relatedTarget,
            dropzoneElement = event.target;
        dropzoneElement.classList.add('drop-target');
        draggableElement.classList.add('can-drop');
    },
    ondragleave: function (event) {
        event.target.classList.remove('drop-target');
        event.relatedTarget.classList.remove('can-drop');
    },

    // drop successful
    ondrop: function (event) {
        console.log(event);
    }
});

Here is a jsfiddle link for the code above: http://jsfiddle.net/hf27hn0c/6/

As you can see, it's not possible to drag & drop the list items into the dropzones. I understand that I'll likely have to remove the items from the parent list manually on drag start, but right now I can't even get the various dragenter, dragleave, or the critical ondrop events to work properly.

Any ideas? Thank you.


Solution

  • interact('.dropzone').dropzone({
        accept: '.draggable',
        overlap: 0.01,
        ...
    

    You're requiring an overlap of 1% of the draggable over the dropzone to qualify for a drop. Because the draggables aren't being moved, the overlap never happens.

    The solution is to add a dragmove to move the draggable or to change the dropzone's overlap to 'pointer'. http://jsfiddle.net/hf27hn0c/7/