Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine what is being dragged from dragenter & dragover events

I'm trying to use the HTML5 draggable API (though I realize it has its problems). So far, the only showstopper I've encountered is that I can't figure out a way to determine what is being dragged when a dragover or dragenter event fires:

el.addEventListener('dragenter', function(e) {   // what is the draggable element? }); 

I realize I could assume that it's the last element to fire a dragstart event, but... multitouch. I've also tried using e.dataTransfer.setData from the dragstart to attach a unique identifier, but apparently that data is inaccessible from dragover/dragenter:

This data will only be available once a drop occurs during the drop event.

So, any ideas?

Update: As of this writing, HTML5 drag-and-drop does not appear to be implemented in any major mobile browser, making the point about multitouch moot in practice. However, I'd like a solution that's guaranteed to work across any implementation of the spec, which does not appear to preclude multiple elements from being dragged simultaneously.

I've posted a working solution below, but it's an ugly hack. I'm still hoping for a better answer.

like image 495
Trevor Burnham Avatar asked Jun 16 '12 17:06

Trevor Burnham


People also ask

What is dragenter?

The dragenter event is fired when a dragged element or text selection enters a valid drop target. The target object is the immediate user selection (the element directly indicated by the user as the drop target), or the <body> element.

Which of the method given in options is used to get the dragged data?

Get the dragged data with the dataTransfer.getData() method. This method will return any data that was set to the same type in the setData() method. The dragged data is the id of the dragged element ("drag1")

What is a drag start?

The ondragstart event occurs when the user starts to drag an element or text selection. Drag and drop is a very common feature in HTML5.


2 Answers

I wanted to add a very clear answer here so that it was obvious to everyone who wanders past here. It's been said several times in other answers, but here it is, as clear as I can make it:

dragover DOES NOT HAVE THE RIGHTS to see the data in the drag event.

This information is only available during the DRAG_START and DRAG_END (drop).

The issue is it's not obvious at all and maddening until you happen to read deeply enough on the spec or places like here.

WORK-AROUND:

As a possible work-around I have added special keys to the DataTransfer object and tested those. For example, to improve efficiency I wanted to look up some "drop target" rules when my drag started instead of every time a "drag over" occurred. To do this I added keys identifying each rule onto the dataTransfer object and tested those with "contains".

ev.originalEvent.dataTransfer.types.includes("allow_drop_in_non_folders") 

And things like that. To be clear, that "includes" is not a magic bullet and can become a performance concern itself. Take care to understand your usage and scenarios.

like image 113
bladnman Avatar answered Oct 10 '22 16:10

bladnman


The short answer to my question turns out to be: No. The WHATWG spec doesn't provide a reference to the element being dragged (called the "source node" in the spec) in the dragenter, dragover, or dragleave events.

Why not? Two reasons:

First, as Jeffery points out in his comment, the WHATWG spec is based on IE5+'s implementation of drag-and-drop, which predated multi-touch devices. (As of this writing, no major multi-touch browser implements HTML drag-and-drop.) In a "single-touch" context, it's easy to store a global reference to the current dragged element on dragstart.

Second, HTML drag-and-drop allows you to drag elements across multiple documents. This is awesome, but it also means that providing a reference to the element being dragged in every dragenter, dragover, or dragleave event wouldn't make sense; you can't reference an element in a different document. It's a strength of the API that those events work the same way whether the drag originated in the same document or a different one.

But the inability to provide serialized information to all drag events, except through dataTransfer.types (as described in my working solution answer), is a glaring omission in the API. I've submitted a proposal for public data in drag events to the WHATWG, and I hope you'll express your support.

like image 45
Trevor Burnham Avatar answered Oct 10 '22 15:10

Trevor Burnham