Search code examples
javascriptdrag-and-drophtml5-draggable

After starting the drag of a DOM element with draggable attribute , Could we stop dragging and exit from drag and drop?


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>


Solution

  • 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>