Drag and drop and drag again using pure javascript

余生颓废 提交于 2020-07-18 07:21:14

问题


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>

UPDATE

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>

回答1:


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; }



回答2:


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!

Original Code

$(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');
    });    
});

The fix

$(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!



来源:https://stackoverflow.com/questions/39133751/drag-and-drop-and-drag-again-using-pure-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!