I am attempting to do a simple drag and drop from one column to another. I am copying the element so that the list on the right can have multiple versions of the element on the left. Don't worry, I'm setting unique IDs before the actual append.
However I also want the user to be able to drag out of the box to delete that same object. But once the DIV is dropped into place (i.e. once it's in column2), it cannot be dragged again. The initial drag and drop works fine.
Solutions I've found deal with jQuery ui. I'm building an angularJS app and am not interesting in using full jQuery nor any additional plug-ins.
Help!
Sample code:
<div id="column1">
<div class="dragme" draggable="true" ondragstart="drag(event)">Item1</div>
<div class="dragme" draggable="true" ondragstart="drag(event)">Item1</div>
</div>
<div id="column2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var newEl = $(document.getElementById(data)).clone()[0];
newEl.id = newEl.id + (+new Date());
ev.target.appendChild(newEl);
}
</script>
It seems that it's not the dragging and dropping that's causing the issue. Any dynamically added content won't drag. I tested this in the console.
FYI...The code below works just fine here, the problem ended up being that my drag/drop was within a draggable container.
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var origThing = document.getElementById(data);
var newThing = origThing.cloneNode(true);
ev.target.appendChild(newThing);
}
.thing {
width: 100px;
height: 2em;
padding: 0.5em;
margin: 0.5em;
background: rgba(0,0,0,0.8);
color: white;
font-family: sans-serif;
}
.col {
width: 130px;
height: 450px;
padding: 1em;
border: 1px solid;
border-radius: 5px;
position: relative;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="col" id="col1">
<div class="thing" draggable="true" ondragstart="drag(event)" id="thing1">THING 1</div>
<div class="thing" draggable="true" ondragstart="drag(event)" id="thing2">THING 2</div>
<div class="thing" draggable="true" ondragstart="drag(event)" id="thing3">THING 3</div>
<div class="thing" draggable="true" ondragstart="drag(event)" id="thing4">THING 4</div>
</div>
<div class="col" id="col2" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>
Here's a pure JavaScript way to drag dynamically created divs around the window.
var divs=[];
var draggingIndex;
var isDown=false;
var startX,startY;
// add some divs dynamically
addDiv(50,50,100,75,'blue','batch1');
addDiv(250,50,50,38,'green','batch1');
// listen to mouse events
window.onmousedown=(function(e){handleMouseDown(e);});
window.onmousemove=(function(e){handleMouseMove(e);});
window.onmouseup=(function(e){handleMouseUp(e);});
function addDiv(x,y,w,h,bk,classname){
var div=document.createElement('div');
div.style.width=w+'px';
div.style.height=h+'px';
div.className=classname;
div.style.position='absolute';
div.style.left=x+'px';
div.style.top=y+'px';
div.style.background=bk;
divs.push({div:div,w:w,h:h});
document.body.appendChild(div);
}
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// get mouse position
startX=parseInt(e.clientX);
startY=parseInt(e.clientY);
// Is any div under the mouse?
draggingIndex=undefined;
for(var i=0;i<divs.length;i++){
var d=divs[i];
var x=parseInt(d.div.style.left);
var y=parseInt(d.div.style.top);
if(startX>x && startX<x+d.w && startY>y && startY<y+d.h){
draggingIndex=i;
isDown=true;
break;
}
}
}
function handleMouseUp(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
isDown=false;
}
function handleMouseMove(e){
if(!isDown){return;}
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// get mouse position
mouseX=parseInt(e.clientX);
mouseY=parseInt(e.clientY);
// move the dragging div by the distance the mouse has moved
var dragging=divs[draggingIndex].div;
var dx=mouseX-startX;
var dy=mouseY-startY;
startX=mouseX;
startY=mouseY;
dragging.style.left=(parseInt(dragging.style.left)+dx)+'px';
dragging.style.top=(parseInt(dragging.style.top)+dy)+'px';
}
body{ background-color: ivory; }
.batch1{border:1px solid red; }
So, the issue turned out to be as simple as the question. My draggable items are custom directives that I set up with draggable="true" and using inline binding like ondrop="drop(event)". So, I didn't realize that elsewhere, there was some very helpful code that was not using delegation, aka, only binding on the initial load. This little caveat is one that affects ANY dynamically loaded DOM elements!
$(document).ready(function() {
$('.dragme').on('mousedown', function(e) {
// disable swiper when user clicks on drawer
$(this).parents('.swiper-wrapper').addClass('no-swiping');
});
$('.dragme').on('mouseup dragend', function(e) {
// re-enable when user is done
$(this).parents('.swiper-wrapper').removeClass('no-swiping');
});
});
$(document).ready(function() {
$(document).on('mousedown', '.dragme', function(e) {
// disable swiper when user clicks on drawer
$(this).parents('.swiper-wrapper').addClass('no-swiping');
});
$(document).on('mouseup dragend', '.dragme', function(e) {
// re-enable when user is done
$(this).parents('.swiper-wrapper').removeClass('no-swiping');
});
});
Note that this code was implemented earlier on to allow dragging in a draggable container!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With