1

I have to stop the drag async after the drag is started. Can I add something in drag event to cancel the drag ?

document.querySelector('#drag-elem').addEventListener('drag', function(e){
  // Stop the drag
  e.preventDefault();
})

document.querySelector('#drag-elem').addEventListener('dragstart', function(e){
  console.log('dragstart')
})
<div draggable='true' id='drag-elem'>Draggable</div>
Alexander van Oostenrijk
  • 4,644
  • 3
  • 23
  • 37
vishnu sandhireddy
  • 1,148
  • 1
  • 7
  • 12
  • Why do you want to stop dragging in the middle of the dragging process? Why don't you just prevent it by removing the draggable attribute? – kol Aug 19 '21 at 06:23
  • By the way, the user can cancel the dragging by pressing Escape during dragging. – kol Aug 19 '21 at 06:25
  • 1
    Thanks kol. Its kind of async validation happening and we are getting validation data after the dragstart event is done. – vishnu sandhireddy Aug 19 '21 at 06:29

1 Answers1

0

You can use a dataIsValid flag to decide if the drop is allowed in both the ondragover and ondrop event handlers. Here is an example where the data is random number between 0 and 1, which is considered valid when larger than 0.5, and the asynchronous validation takes one whole second. Try dragging the Source over the Target and wait for at least one second before releasing the left mouse button.

let dataIsValid = false;

function validateData(data) {
  dataIsValid = data.value > 0.5;
  console.log(`Data is ${dataIsValid ? "valid" : "invalid"}: ${data.value.toFixed(2)}`);
}

function onDragStart(event) {
  // Create data to be transferred
  const data = {
    value: Math.random()
  };
  event.dataTransfer.setData("text", JSON.stringify(data));
  event.target.textContent = data.value.toFixed(2);
  
  // Start asynchronous validation
  dataIsValid = false;
  setTimeout(() => validateData(data), 1000);
}

function onDragOver(event) {
  if (dataIsValid) {
    event.preventDefault();  
  }
}

function onDrop(event) {
  if (dataIsValid) {
    event.preventDefault();  
    const data = JSON.parse(event.dataTransfer.getData("text"));
    event.target.textContent = data.value.toFixed(2);
  }
}
div.circle {
  display: inline-block;
  width: 100px;
  height: 100px;
  border-radius: 50px;
  text-align: center;
  vertical-align: middle;
  line-height: 100px;
  font-family: Arial, Helvetica, sans-serif;
}

div#source {
  background: coral;
}

div#target {
  background: lightblue;
}
<div id="source" class="circle" draggable="true" ondragstart="onDragStart(event)">Source</div>
<div id="target" class="circle" ondragover="onDragOver(event)" ondrop="onDrop(event)">Target</div>
kol
  • 27,881
  • 12
  • 83
  • 120
  • 1
    Thanks kol , even though my intention is to cancel the drop. That seems to be not possible. Liked this idea of maintaining global state, and invalidating drop. – vishnu sandhireddy Aug 19 '21 at 07:21
  • 1
    You're welcome. I think it's not possible because it might confuse the user. Imagine that you start a drag, then suddenly the dragged object disappears from under your mouse pointer, although you are still holding down the left button. I'd think I accidentally released the button so I'd try dragging again. – kol Aug 19 '21 at 07:26