I recently incorporated drag-and-drop functionality into my portfolio, and let me tell you—it was my first time working with this event, and it turned out to be more complex than I expected. 😨 I created a page that allows users to drag and drop tasks and lists, similar to Trello, and I quickly realized there’s a lot more to it than meets the eye.
In this post, I’d like to share the insights and lessons I gained while building and troubleshooting this feature.
The DragEvent
is a DOM event that facilitates drag-and-drop interactions within a web page. This event is triggered at various stages of a user’s drag action, typically initiated by a pointer device like a mouse. When a user clicks on a DOM element and drags it to a new position, the DragEvent
comes into play. To make an element draggable, you need to add the draggable
attribute to it. Once this attribute is set, the element will follow the pointer as it is dragged across the screen.
A key feature of DragEvent
is the dataTransfer
property. This property allows you to transfer data during the drag event, making it possible to move or copy information from one part of the application to another during the drag-and-drop interaction.
The dragstart
event is triggered when a user begins dragging an element. This event is cancelable and can bubble up through the DOM, meaning it can be captured by ancestor elements if needed.
To attach this event to a target element, you can use addEventListener
with dragstart
as shown below:
Initialize Data Transfer
The dragstart
event is commonly used to prepare data for transfer. For example, you can determine what data should be transferred during the drag operation and set it in the dataTransfer
object. This allows you to pass data to other elements during the drag-and-drop process.
Setting Drag Effects
You can use the dataTransfer.effectAllowed
property during the dragstart
event to specify the allowed drag effects (such as copy, move, or link). This helps to control or guide the user on what actions are permitted during the drag operation.
Possible options
none
copy
move
link
copyMove
linkMove
all
uninitialized
Custom Drag Image
If you want to display a custom image while dragging, you can set it using event.dataTransfer.setDragImage()
. This allows you to provide a more intuitive or branded experience during the drag operation.
If you want to display specific DOM elements while dragging, you can do it like this:
Explanation:
- Using an Image:
- Using a Custom DOM Element:
These approaches allow you to have complete control over what users see during a drag operation, whether it's a simple image or a fully styled DOM element.
Accessibility Considerations
It’s important to consider accessibility when implementing drag-and-drop functionality. During the dragstart
event, you can set the aria-grabbed
attribute to notify screen reader users that a drag operation has started.
The drag
event is fired repeatedly as an element is being dragged. It occurs whenever the mouse or pointer is moved while the element is being dragged.
This event is useful when you need to provide real-time feedback to the user about the element being dragged. This can include updating the UI, dynamically adjusting the position of other elements, or tracking the movement of the dragged element.
This event is fired every few hundred milliseconds.
The dragover
event is fired when a dragged element is being moved over a valid drop target. It occurs whenever the pointer is over an element that could potentially receive the dragged item.
The main purpose of the dragover
event is to determine whether the dragged item can be dropped in the current location. It’s also where you typically call event.preventDefault()
to allow dropping the item on that target. Without calling preventDefault()
, the drop will not be allowed by default.
Additionally, you might apply some styles to the drop target during the dragover
event, providing visual feedback to the user that the item can be dropped there.
This event is also fired every few hundred milliseconds.
Key Differences between drop
and dropover
- Event Triggering:
- Purpose:
- Default Behavior:
The dragleave
event is triggered when a dragged element leaves a valid drop target. This event is useful when you want to undo or reset changes made when an element was dragged over a drop target but is then dragged out of that area without being dropped.
Points to Note:
When using the dragleave
event to implement functionality, it's important to note that if the target element contains child elements, the dragleave
event will be triggered on the target element when the dragged element enters one of its child elements. Simultaneously, a dragenter
event will be triggered on the child element. This occurs because, from the perspective of the parent element, the dragged element is "leaving" its boundary when it moves into a child element.
How to Resolve This Issue
When you set pointer-events: none;
on a child element, it will not respond to any mouse or pointer events. This means that the element will behave as if it isn't there when it comes to pointer interactions—dragging the mouse over it won't trigger drag
, dragenter
, dragleave
, click
, or any other pointer events on that element.
So, if you apply this style attribute to the child elements where you want to prevent drag events, the drag event will be fired on the closest ancestor that can receive pointer events.
The drop
event is triggered when a dragged item is dropped onto a valid drop target. This event allows you to specify what should happen when the user drops an item in a particular location, such as moving data, changing the UI, or executing some other action.
For the drop
event to be triggered, the dragover
event on the drop target must have its default behavior prevented (using event.preventDefault()
), which allows the target to accept the drop.
You can also retrieve any data that was set during the dragstart
event using the dataTransfer
object by using the method getData
.
Handling the drop
Event
- Preventing the Default Behavior: The default action of a
drop
event may include things like redirecting the browser (if a link is dragged and dropped). To handle the drop properly, always useevent.preventDefault()
within thedrop
event handler. - Processing Data: You can use the
drop
event to process the data that was transferred during the drag operation, which might involve adding content to the page, moving items between lists, or performing other dynamic updates.
The dragend
event is part of the drag-and-drop API and is triggered when a drag operation has been completed. This event is fired on the element that was being dragged, regardless of whether the drag was successful (i.e., whether the item was dropped on a valid drop target) or not (i.e., the item was released outside a valid drop target).
So, this dragend
event is commonly used to clean up any changes made during the drag operation, such as removing visual feedback (e.g., highlighting drop zones) or resetting styles that were applied during dragstart
or dragover
. It can also be used to handle any final state updates after the drag operation, such as updating the UI to reflect that the drag has ended, regardless of whether it was successful or not.