-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfile-drop-zone.ts
126 lines (109 loc) · 3.36 KB
/
file-drop-zone.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
interface FileDropZoneComponentArgs {
disabled: boolean;
onDrop?: (files: File[]) => void;
onDragEnter?: () => void;
onDragLeave?: () => void;
}
export default class FileDropZoneComponent extends Component<FileDropZoneComponentArgs> {
@tracked hovering = false;
@tracked dragging = false;
@tracked windowEnteredCounter = 0;
@action
registerListener(element) {
window.addEventListener('dragenter', this.onWindowDragEnter, false);
window.addEventListener('dragleave', this.onWindowDragLeave), false;
window.addEventListener('dragover', this.onWindowDragOver, false);
window.addEventListener('drop', this.onWindowDrop, false);
element.addEventListener('dragenter', this.onDragEnter, false);
element.addEventListener('dragleave', this.onDragLeave), false;
element.addEventListener('dragover', this.onDragOver, false);
element.addEventListener('drop', this.onDrop, false);
}
@action
unregisterListener(element) {
window.removeEventListener('dragenter', this.onWindowDragEnter, false);
window.removeEventListener('dragleave', this.onWindowDragLeave, false);
window.removeEventListener('dragover', this.onWindowDragOver, false);
window.removeEventListener('drop', this.onWindowDrop, false);
element.removeEventListener('dragenter', this.onDragEnter, false);
element.removeEventListener('dragleave', this.onDragLeave), false;
element.removeEventListener('dragover', this.onDragOver, false);
element.removeEventListener('drop', this.onDrop, false);
}
@action
onWindowDragEnter(e: DragEvent) {
this.dragging = true;
++this.windowEnteredCounter;
}
@action
onWindowDragLeave() {
if (--this.windowEnteredCounter == 0) {
this.dragging = false;
}
}
@action
onWindowDragOver(e: DragEvent) {
e.preventDefault();
}
@action
onWindowDrop(e: DragEvent) {
e.preventDefault();
this.reset();
}
@action
onDragEnter(e: DragEvent) {
this.hovering = true;
if (!this.args.disabled && this.args.onDragEnter) {
this.args.onDragEnter(this.extractFiles(e).length);
}
}
@action
onDragLeave() {
this.hovering = false;
if (!this.args.disabled && this.args.onDragLeave) {
this.args.onDragLeave();
}
}
@action
onDragOver(e: DragEvent) {
e.preventDefault();
}
@action
onDrop(e: DragEvent) {
e.preventDefault();
this.reset();
if (this.args.disabled) {
return true;
}
if (this.args.onDrop) {
this.args.onDrop(this.extractFiles(e));
}
}
reset() {
this.dragging = false;
this.hovering = false;
this.windowEnteredCounter = 0;
}
extractFiles(event: DragEvent) {
let files = [];
if (event.dataTransfer?.items) {
// Use DataTransferItemList interface to access the file(s)
for (var i = 0; i < event.dataTransfer.items.length; i++) {
// If dropped items aren't files, reject them
const item = event.dataTransfer.items[i];
if (item.kind === 'file') {
files.push(item.getAsFile());
}
}
} else {
// Use DataTransfer interface to access the file(s)
for (var j = 0; j < event.dataTransfer.files.length; j++) {
files.push(event.dataTransfer.files[j]);
}
}
return files;
}
}