Skip to content

Commit 9fa4c04

Browse files
committed
learn about Drag and Drop events
1 parent b3615ee commit 9fa4c04

File tree

4 files changed

+111
-1
lines changed

4 files changed

+111
-1
lines changed

Working-with-Events/README.md

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
| [Using Event Delegation](#using-event-delegation) |
1414
| [Triggering DOM Elements Programmatically](#triggering-dom-elements-programmatically) |
1515
| [Event Handler Functions and `this`](#event-handler-functions-and-this) |
16+
| [Drag and Drop Events](#drag-and-drop-events) |
1617

1718
## [Introduction to Events in JavaScript](https://drive.google.com/uc?export=view&id=1tfi-wZ9BYL2wISnyZ2JCcutRPApHpyCV)
1819

@@ -701,4 +702,60 @@ If an event handler is bound to the `div.outer` element, and the user clicks on
701702
702703
It is important to keep in mind the event bubbling and capturing phase as well when considering the value of `this` in nested elements.
703704
704-
It's important to note that when using arrow functions as event handler functions, the `this` keyword behaves differently. Arrow functions inherit the `this` value of the enclosing lexical scope, which is often the global object or the object that the arrow function is defined in. Therefore, if we use an arrow function as an event handler, the `this` keyword will not refer to the DOM element that the event was triggered on.
705+
It's important to note that when using arrow functions as event handler functions, the `this` keyword behaves differently. Arrow functions inherit the `this` value of the enclosing lexical scope, which is often the global object or the object that the arrow function is defined in. Therefore, if we use an arrow function as an event handler, the `this` keyword will not refer to the DOM element that the event was triggered on.
706+
707+
## [Drag and Drop Events](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API)
708+
709+
<img src="https://drive.google.com/uc?export=view&id=1kkXlf52mdwARgPsNL_8UIbvpMOatWQfi" height="400" width="800" alt="academind slide">
710+
711+
- To make elements draggable:
712+
713+
- Mark them by adding the [`draggable`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable) attribute or setting the [`draggable`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable) property on the DOM elements to `true`.
714+
- Both the attribute or the property need to be set to `true`.
715+
716+
- Listen to the [`dragstart`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragstart_event) event on the draggable element, which is triggered when a user starts dragging the element.
717+
718+
- In the event listener, you can interact with the event object to describe the drag operation, such as copying or moving.
719+
- You can also append data to the event to make sure that the drag and drop operation works together.
720+
721+
- To mark the areas where an item can be dropped, add an event listener to the element where the other element can be dropped:
722+
- Add a listener to the [`dragenter`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragenter_event) and [`dragover`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragover_event) events.
723+
- Call [`preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) in the event listeners to allow a drop operation.
724+
- Optionally listen to the [`dragleave`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragleave_event) event if you want to update the UI.
725+
726+
- Listen to the [`drop`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event) event on the same element where you listened to [`dragenter`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragenter_event) and [`dragover`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragover_event).
727+
- The drop event is only triggered if you prevented the default in dragenter and dragover, and the item is then dropped onto that same element.
728+
- In the [`drop`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event) event, you can do whatever you want to do upon a drop.
729+
730+
- Optionally, listen to the [`dragend`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragend_event) event on the dragged element itself, where you could update the UI or some data.
731+
- The [`dragend`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragend_event) event is always fired even if the drop is cancelled.
732+
- You will get some property on the event object which tells you whether the drop was successful or not.
733+
734+
You can check whether a [`drop`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event) operation succeeded or not by listening to the `drop` event and checking the `dataTransfer.dropEffect` property of the event object.
735+
736+
When the drop event fires, the `dataTransfer.dropEffect` property will contain one of the following string values:
737+
738+
- "none" if the drop operation was not allowed on the drop target
739+
- "copy" if the dragged item was copied to the drop target
740+
- "move" if the dragged item was moved to the drop target
741+
- "link" if the dragged item was linked to the drop target
742+
743+
You can use this value to determine whether the drop operation succeeded or not and take the appropriate action in your code.
744+
745+
Some Useful Attributes and Methods:
746+
747+
- [event.dataTransfer](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer)
748+
749+
- [DataTransfer: setData() method](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setData)
750+
751+
- [DataTransfer: effectAllowed property](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed)
752+
753+
- [DataTransfer: getData() method](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/getData)
754+
755+
Readings:
756+
757+
- [Drag-And-Drop Events In JavaScript](https://blog.openreplay.com/drag-and-drop-events-in-javascript/)
758+
759+
- [JavaScript Drag and Drop](https://www.javascripttutorial.net/web-apis/javascript-drag-and-drop/)
760+
761+
- [Recommended Drag Types](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types)

Working-with-Events/projects/events-01-starting-setup/assets/scripts/app.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class ProjectItem {
8282
this.updateProjectListHandler = updateProjectListFunction;
8383
this.connectMoreInfoButton();
8484
this.connectSwitchButton(type);
85+
this.connectDrag();
8586
}
8687

8788
showMoreInfoHandler() {
@@ -97,6 +98,17 @@ class ProjectItem {
9798
this.hasActiveTooltip = true;
9899
}
99100

101+
connectDrag(){
102+
const item = document.getElementById(this.id)
103+
item.addEventListener('dragstart', event => {
104+
event.dataTransfer.setData('text/plain', this.id);
105+
event.dataTransfer.effectAllowed='move';
106+
});
107+
item.addEventListener('dragend', event => {
108+
console.log(event);
109+
});
110+
}
111+
100112
connectMoreInfoButton(){
101113
const prjItemElement = document.getElementById(this.id);
102114
const moreInfoBtn = prjItemElement.querySelector('button:first-of-type');
@@ -126,6 +138,40 @@ class ProjectList {
126138
for (const prjItem of prjItems) {
127139
this.projects.push(new ProjectItem(prjItem.id, this.switchProject.bind(this), this.type));
128140
}
141+
this.connectDroppable();
142+
}
143+
144+
connectDroppable(){
145+
const list = document.querySelector(`#${this.type}-projects ul`);
146+
147+
list.addEventListener('dragenter', event => {
148+
if (event.dataTransfer.types[0]==='text/plain'){
149+
list.parentElement.classList.add('droppable');
150+
event.preventDefault();
151+
}
152+
});
153+
154+
list.addEventListener('dragover', event => {
155+
if (event.dataTransfer.types[0]==='text/plain'){
156+
event.preventDefault();
157+
}
158+
});
159+
160+
list.addEventListener('dragleave', event => {
161+
if (event.relatedTarget.closest(`#${this.type}-projects ul`) !== list) {
162+
list.parentElement.classList.remove('droppable');
163+
}
164+
});
165+
166+
list.addEventListener('drop', event => {
167+
const prjId = event.dataTransfer.getData('text/plain');
168+
if (this.projects.find(p => p.id === prjId)) {
169+
return;
170+
}
171+
document.getElementById(prjId).querySelector('button:last-of-type').click();
172+
list.parentElement.classList.remove('droppable');
173+
});
174+
129175
}
130176

131177
setSwitchHandlerFunction(switchHandlerFunction) {

Working-with-Events/projects/events-01-starting-setup/assets/styles/app.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ button:active {
9191
background: white;
9292
}
9393

94+
.droppable {
95+
background-color: #ffe0ec;
96+
}
97+
9498
#active-projects {
9599
border: 1px solid #870099;
96100
}

Working-with-Events/projects/events-01-starting-setup/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ <h2>Active Projects</h2>
2626
id="p1"
2727
data-extra-info="Got lifetime access, but would be nice to finish it soon!"
2828
class="card"
29+
draggable="true"
2930
>
3031
<h2>Finish the Course</h2>
3132
<p>Finish the course within the next two weeks.</p>
@@ -36,6 +37,7 @@ <h2>Finish the Course</h2>
3637
id="p2"
3738
data-extra-info="Not really a business topic but still important."
3839
class="card"
40+
draggable="true"
3941
>
4042
<h2>Buy Groceries</h2>
4143
<p>Don't forget to pick up groceries today.</p>
@@ -53,6 +55,7 @@ <h2>Finished Projects</h2>
5355
id="p3"
5456
data-extra-info="Super important conference! Fictional but still!"
5557
class="card"
58+
draggable="true"
5659
>
5760
<h2>Book Hotel</h2>
5861
<p>

0 commit comments

Comments
 (0)