0

Have a look at this fiddle: https://jsfiddle.net/zanpx9mw/1/

Code:

const draggable_element = document.getElementById("draggable_element");

draggable_element.addEventListener("dragstart", (e) => {
  const rect = e.srcElement.getBoundingClientRect();
  const dt = e.dataTransfer;
  dt.setData("dx", `${Math.round(e.clientX - rect.x)}`);
  dt.setData("dy", `${Math.round(e.clientY - rect.y)}`);
  [...dt.items].forEach(it => {
    console.log(`dragstart ${it.type}: ${dt.getData(it.type)}`);
  });
});

draggable_element.addEventListener("dragover", (e) => {
  const dt = e.dataTransfer;
  [...dt.items].forEach(it => {
    console.log(`dragover ${it.type}: ${dt.getData(it.type)}`);
  });
});

On Firefox I can store data inside the events dataTransfer object in the dragstart event and read it later in the dragover event.

In Chromium/Chrome however I can store the data and read it successfully inside the dragstart event but not in the dragover event anymore. Strangely items with the expected names are still present but the data seems to be empty.

There is a funny workaround though: I can just save the data inside the item type but that seems wrong..

Is this known behavior? Am I doing something wrong?

frans
  • 8,868
  • 11
  • 58
  • 132

1 Answers1

1

Looks like Chrome supports getData() only on drop events for security reasons (taken from this very similar question).

To circumvent those "security" measures you would have to write the data to the type like this:

const draggable_element = document.getElementById("draggable_element");

function int_list(dt, name) {
  for(const it of dt.items) {
    if (it.type.startsWith(`${name}`))  {
        return it.type.split("_").slice(1).map(x=>parseInt(x));
    }
  }
}

draggable_element.addEventListener("dragstart", (e) => {
  const rect = e.srcElement.getBoundingClientRect();
  e.dataTransfer.setData(`pos_${Math.round(e.clientX - rect.x)}_${Math.round(e.clientY - rect.y)}`, '');
});

draggable_element.addEventListener("dragover", (e) => {
  const pos = int_list(e.dataTransfer, "pos");
  e.srcElement.style.left = `${e.x - pos[0]}px`;
  e.srcElement.style.top = `${e.y - pos[1]}px`;
});

see working example https://jsfiddle.net/g7608m1j/

frans
  • 8,868
  • 11
  • 58
  • 132