Thanh Trung
Thanh Trung

Reputation: 3804

How to transfer the whole element using html5 event.dataTransfer?

I want to remember or get data of the current drag element. This is what I did :

$('.source_element').on('dragstart', function(e){
   e.originalEvent.dataTransfer.setData("source", this); 
});

$('.destination').on('drop', function(e){
   var source = e.originalEvent.dataTransfer.getData('source');
   console.log(source);
   console.log(source.className);
   console.log($(source));
   $(this).html($(source).html());

   e.preventDefault();
});

The first console.log show [object HTMLDivElement] as a string, not an object, second undefined, third throws an error.

So I suspect that dataTransfer.setData only accept the data as a string, object is not allowed. If that's the case, how do you solve this problem, how can I remember which element is being dragged without knowing its specific ID ?

Upvotes: 5

Views: 7513

Answers (3)

gray
gray

Reputation: 998

You could also do this by inserting a stringified JSON object to the dataTransfer.setData part:

Add the HTML element (use outerHTML so it's a string):

var dragData = {element:originalElement.outerHTML, type:'move-hovered'}
dragData = JSON.stringify(dragData);
event.dataTransfer.setData("text/plain", dragData);

In the above, I create the dragData object with 2 keys - one is the element, and the other, move-hovered, is just a name for the drag event, so you can identify it.

Then JSON parse it when dropped:

var data = e.dataTransfer.getData("text");
var dragData = JSON.parse(data)
var element = dragData.element

Not sure if there's a limit on the length of the text that can be passed, but this is working for me. The main issue though is that there is no reference to the original HTML element, as a new string is used.

And you have to recreate the HTML node when dropped:

var dragDataElement = document.createElement('div')
dragDataElement.innerHTML = dragData.element
originalElement = dragDataElement.firstChild

Upvotes: 0

Seph Reed
Seph Reed

Reputation: 10928

I'm not a fan of globals, but sometimes they suit the problem. If you want to be able to move an HTMLElement with some data, try this:

window.dragDepo = {};
const dragID = "unique_dragging_name";
sourceEl.addEventListener("dragstart", (event) => {
  window.dragDepo[dragID] = { el: sourceEl, origin: "where it was before" }
  event.dataTransfer.setData("text/plain", dragID);
});

// clear global data asap
sourceEl.addEventListener("dragend", (event) => window.dragDepo[dragID] = undefined);

.

destinationEl.addEventListener("drop", (event) => {
  const dragID = event.dataTransfer.getData("text/plain");
  dragData = window.dragDepo[dragID];
});

Upvotes: 3

Musa
Musa

Reputation: 97672

Just use some string to uniquely identify the element, like giving each element an id or a data attribute

$('.source_element').on('dragstart', function(e){
   var id = 'drag-'+(new Date()).getTime();
   this.id = id;
   //$(this).attr('data-drag', id);
   e.originalEvent.dataTransfer.setData("source", id); 
});

$('.destination').on('drop', function(e){
   var source = e.originalEvent.dataTransfer.getData('source');
   console.log(source);
   console.log($('#'+source));
   $(this).html($('#'+source).html());
   //console.log($('[data-id="'+source+'"]'));
   //$(this).html($('[data-id="'+source+'"]').html());

   e.preventDefault();
});

Upvotes: 4

Related Questions