Skip to content Skip to sidebar Skip to footer

Issue With Drag And Drop API Or?

I'm encountering an issue with the HTML5 Drag and Drop API. Long story short, there are three events other than dragstart, dragover, and drop, which are critical to my objective. T

Solution 1:

The problem, when you try to grab the left element close to its right edge, is that mouseleave is triggered as soon as you move the mouse to the right, before dragstart has a chance to be triggered. You can see the events in this code snippet:

var d = document.getElementById('draggable')
var t = document.getElementById('target')

d.addEventListener('mousedown', doThis)
d.addEventListener('mouseleave', thenThis)

function doThis(){
  console.log('mousedown');
  d.setAttribute('draggable', true);
  d.addEventListener('dragstart', dragStart);
  t.style.background = 'black';
  t.addEventListener('dragover', dragOver);
  t.addEventListener('drop', drop);
}

function thenThis(){
  console.log('mouseleave');
  d.setAttribute('draggable', false);
  d.removeEventListener('dragstart', dragStart);
  t.style.background = 'none';
  t.removeEventListener('dragover', dragOver);
  t.removeEventListener('drop', drop);
}

function dragStart(e){
  console.log('dragstart');
  e.dataTransfer.setData('text/plain', e.target.id);
  e.dataTransfer.effectAllowed = 'move';
}

function dragOver(e){
  e.preventDefault();
}

function drop(e){
  var data = e.dataTransfer.getData('text/plain');
  e.preventDefault();
  e.target.parentElement.appendChild(document.getElementById(data));
}
body {
  display: flex;
  justify-content: space-around;
}

.square {
  width: 50px;
  height: 50px;
}

#draggable {
  background: purple;
}

#target {
  border: solid 3px black;
}
<div id="draggable" class="square"></div>
<div id="target" class="square"></div>

To avoid that situation, you can capture the mouse instead of processing mouseleave. Once the dragging operation begins, you can release the mouse capture and rely on the dragend event. The draggable element properties will be reset when the mouse is released by the user (if the element was not dragged) or when the drag operation ends.

var d = document.getElementById('draggable')
var t = document.getElementById('target')
var releaseCapture = null;

d.addEventListener('mousedown', mouseDown);
d.addEventListener('dragend', resetDraggableElement);

function mouseDown() {
  releaseCapture = captureMouse(resetDraggableElement);
  d.setAttribute('draggable', true);
  d.addEventListener('dragstart', dragStart);
  t.style.background = 'black';
  t.addEventListener('dragover', dragOver);
  t.addEventListener('drop', drop);
}

function resetDraggableElement() {
  d.setAttribute('draggable', false);
  d.removeEventListener('dragstart', dragStart);
  t.style.background = 'none';
  t.removeEventListener('dragover', dragOver);
  t.removeEventListener('drop', drop);
}

function dragStart(e) {
  if (releaseCapture) {
    releaseCapture();
    releaseCapture = null;
  }
  e.dataTransfer.setData('text/plain', e.target.id);
  e.dataTransfer.effectAllowed = 'move';
}

function dragOver(e) {
  e.preventDefault();
}

function drop(e) {
  var data = e.dataTransfer.getData('text/plain');
  e.preventDefault();
  e.target.parentElement.appendChild(document.getElementById(data));
}

function captureMouse(mouseUpHandler) {
  var releaseCapture = function() {
    document.removeEventListener("mouseup", lostCaptureHandler, false);
  }
  var lostCaptureHandler = function() {
    releaseCapture();
    if (mouseUpHandler) {
      mouseUpHandler();
    }
  };
  document.addEventListener("mouseup", lostCaptureHandler, false);
  return releaseCapture;
}
body {
  display: flex;
  justify-content: space-around;
}

.square {
  width: 50px;
  height: 50px;
}

#draggable {
  background: purple;
}

#target {
  border: solid 3px black;
}
<div id="draggable" class="square"></div>
<div id="target" class="square"></div>

Post a Comment for "Issue With Drag And Drop API Or?"