Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to set event.dataTransfer asynchronously after drag start?

Currently I am working on a scenario that I need to change the data attached to a dragging element after the dragging starts. Basically the drop zones are input fields or textareas so i would like to use the native event.dataTransfer.setData since the native drag-drop can make the caret move with mouse.

Everything works perfectly at the beginning if i just call the setData() synchronously in the listener of dragstart event.

dragItem.addEventListener("dragstart",function(event){  
     event.dataTransfer.setData("text/plain","data set in dragstart");
}) 

However, my scenario could be that the data is from an asynchronouly callback function like an AJAX request. Then I attempted to call setData() in this callback function but nothing seems to be successfully set.

dragItem.addEventListener("dragstart",function(event){

  event.dataTransfer.setData("text/plain","data set in dragstart");

  //like a callback in Ajax or resolve function of a promise.
  setTimeout(function(){
    console.log("attempt to set data asynchonrously after drag start");
    event.dataTransfer.setData("text/plain","asynchonrously set data");

    //looks like failed, the console output is empty, even not the original set one
    console.log(event.dataTransfer.getData("text/plain"));
  },200)

}) 

I also tried to change the data in dragenter and even drop event listeners of the drop zones. But there was still no luck.

This plunker shows what i have tried.

Then i referred to the MDN API document to find offical api description of the dataTransfer object. But there is nothing about problems like asynchronously using setData after drag start. One really weird thing is that if i try to compare the two dataTransfer references in dragstart and drop event, the are NOT the same object. Now I have no clue what is actually happening.

So my questions are

  1. Is it possible to set the data in dataTransfer after the dragging is started with the native APIs (without using event.preventDefault) ?
  2. If the first question's answer is NO, what kind of workaround could I try? I could think of something about how to save and get the data to transfer. My main concern is that if event.preventDefault() is used on drop, it is not easy to get the caret move with mouse like the native dropping does.
like image 568
MMhunter Avatar asked Aug 06 '16 04:08

MMhunter


1 Answers

Here is your answer. Firstly,You can only set data in your dragstart event. So, every time any dragstart event starts it sets value and what ever you set asynchronouly will not get reflected no matter what.

So, one thing that you can do is have a global object and set that on drag start event like this:

var someObj = {
   asd : 'something'
}

and set in you dragstart callback, like this:

dragItem.addEventListener("dragstart",function(event){

      event.dataTransfer.setData("text/plain", someObj.asd);
      dataTransferObject = event.dataTransfer;

      setTimeout(function(){
        console.log("attempt to set data asynchonrously after drag start");
        //event.dataTransfer.setData("text/plain","asynchonrously set data");

        someObj.asd = 'asynchonrously';
        //looks like failed, the console output is empty
        console.log(event.dataTransfer.getData("text/plain"));
      }, 100)

    })    

Object is by default reference type. Now, You can set someObj.asd to any value you want and you will see new value reflected. But there is a problem with this approach, value will be reflected after drop happens means after event has been ended.

So, to solve your problem what you can do is don't set any value on dragstart just set some value to someObj.asd on drag start and use someObj.asd on drop.

Here is a link of what i'm trying to explain: https://plnkr.co/edit/SZhI9lGRI37eEd1nWfhn?p=preview

see console on drop event you will see reflected value there.

DON'T SEE UI JUST GO FOR CONSOLE

like image 89
Amitpal Rawat Avatar answered Nov 01 '22 06:11

Amitpal Rawat