EN
JavaScript - drag element from one container to other one
21 points
In this short article, we would like to show how in JavaScript write simple logic that lets' drag some elements from one place to another.

Using the below Dragger
class we are able to create few independent draggable workspaces - items are draggable only between indicated groups.
Note: presented solution doesn't work on touched screens - mouse needed.
Simple usage:
xxxxxxxxxx
1
var workspace = document.querySelector('.workspace');
2
3
var dragger = new Dragger(workspace);
4
5
dragger.addDropzone(workspace.querySelector('.dropzone-1')); // place to put draggable item
6
dragger.addDropzone(workspace.querySelector('.dropzone-2')); // place to put draggable item
7
dragger.addDropzone(workspace.querySelector('.dropzone-3')); // place to put draggable item
8
dragger.addDropzone(workspace.querySelector('.dropzone-4')); // place to put draggable item
9
10
dragger.addDraggable(workspace.querySelector('.draggable-1')); // draggable item
11
dragger.addDraggable(workspace.querySelector('.draggable-2')); // draggable item
12
13
dragger.enable();
Practical example:
xxxxxxxxxx
1
2
<html>
3
<head>
4
<script>
5
6
var counter = 0;
7
8
function checkDraggable(draggable) {
9
return draggable.$$_TYPE_$$ == 'DRAGGABLE'
10
};
11
12
function checkDropzone(dropzone, selection) {
13
return dropzone.$$_TYPE_$$ == 'DEROPZONE' && dropzone.$$_ID_$$ == selection.$$_ID_$$;
14
};
15
16
function Dragger(workspace) {
17
18
var id = ++counter;
19
var enabled = false;
20
var selection = null;
21
22
var onDrag = function(e) {
23
// nothing here ...
24
};
25
26
var onDrop = function(e) {
27
if (selection) {
28
var dropzone = e.target;
29
if (checkDropzone(dropzone, selection)) {
30
dropzone.classList.remove('active');
31
dropzone.classList.add('default');
32
dropzone.appendChild(selection);
33
}
34
}
35
};
36
37
var onDragstart = function(e) {
38
var draggable = e.target;
39
if (checkDraggable(draggable)) {
40
draggable.classList.remove('default');
41
draggable.classList.add('active');
42
selection = draggable;
43
}
44
};
45
46
var onDragend = function(e) {
47
if (selection) {
48
var draggable = e.target;
49
if (checkDraggable(draggable)) {
50
draggable.classList.remove('active');
51
draggable.classList.add('default');
52
selection = null;
53
}
54
}
55
};
56
57
var onDragover = function(e) {
58
e.preventDefault();
59
};
60
61
var onDragenter = function(e) {
62
if (selection) {
63
var dropzone = e.target;
64
if (checkDropzone(dropzone, selection)) {
65
dropzone.classList.remove('default');
66
dropzone.classList.add('active');
67
}
68
}
69
};
70
71
var onDragleave = function(e) {
72
if (selection) {
73
var dropzone = e.target;
74
if (checkDropzone(dropzone, selection)) {
75
dropzone.classList.remove('active');
76
dropzone.classList.add('default');
77
}
78
}
79
};
80
81
this.addDraggable = function(handle) {
82
if (handle.$$_TYPE_$$) {
83
throw new Error('Element already in use.');
84
}
85
handle.draggable = true;
86
handle.$$_ID_$$ = id;
87
handle.$$_TYPE_$$ = 'DRAGGABLE';
88
handle.classList.add('default');
89
};
90
91
this.removeDraggable = function(handle) {
92
if (handle.$$_TYPE_$$ == 'DRAGGABLE') {
93
handle.draggable = false;
94
delete handle.$$_ID_$$;
95
delete handle.$$_TYPE_$$;
96
handle.classList.remove('default');
97
}
98
else
99
throw new Error('Element is not draggable.');
100
};
101
102
this.addDropzone = function(handle) {
103
if (handle.$$_TYPE_$$) {
104
throw new Error('Element already in use.');
105
}
106
handle.$$_ID_$$ = id;
107
handle.$$_TYPE_$$ = 'DEROPZONE';
108
handle.classList.add('default');
109
};
110
111
this.removeDropzone = function(handle) {
112
if (handle.$$_TYPE_$$ == 'DEROPZONE') {
113
delete handle.$$_ID_$$;
114
delete handle.$$_TYPE_$$;
115
handle.classList.add('default');
116
}
117
else
118
throw new Error('Element is not dropzone.');
119
};
120
121
this.enable = function() {
122
if (enabled == true) {
123
return;
124
}
125
workspace.addEventListener('drag', onDrag, false);
126
workspace.addEventListener('drop', onDrop, false);
127
workspace.addEventListener('dragstart', onDragstart, false);
128
workspace.addEventListener('dragend', onDragend, false);
129
workspace.addEventListener('dragover', onDragover, false);
130
workspace.addEventListener('dragenter', onDragenter, false);
131
workspace.addEventListener('dragleave', onDragleave, false);
132
enabled = false;
133
};
134
135
this.disable = function() {
136
if (enabled == false) {
137
return;
138
}
139
workspace.removeEventListener('drag', onDrag, false);
140
workspace.removeEventListener('drop', onDrop, false);
141
workspace.removeEventListener('dragstart', onDragstart, false);
142
workspace.removeEventListener('dragend', onDragend, false);
143
workspace.removeEventListener('dragover', onDragover, false);
144
workspace.removeEventListener('dragenter', onDragenter, false);
145
workspace.removeEventListener('dragleave', onDragleave, false);
146
enabled = true;
147
};
148
}
149
150
</script>
151
</head>
152
<body>
153
<style>
154
155
.list > * + * {
156
margin: 10px 0 0 0;
157
}
158
159
.draggable {
160
width: 200px;
161
height: 20px;
162
text-align: center;
163
}
164
165
.draggable.default {
166
background: white;
167
opacity: 1.0;
168
}
169
170
.draggable.active {
171
background: orange;
172
opacity: 0.5;
173
}
174
175
.dropzone {
176
padding: 10px;
177
background: #fbea68;
178
width: 200px;
179
height: 20px;
180
}
181
182
.dropzone.default {
183
border: 3px solid #FFFFFF;
184
}
185
186
.dropzone.active {
187
border: 3px dotted #c5b858;
188
}
189
190
</style>
191
192
<div style="display: flex">
193
194
<div class="workspace list">
195
<div class="item dropzone">
196
<div class="item draggable">
197
Drag me down!
198
</div>
199
</div>
200
<div class="item dropzone"></div>
201
<div class="item dropzone"></div>
202
<div class="item dropzone"></div>
203
</div>
204
205
<div class="workspace list">
206
<div class="item dropzone">
207
<div class="item draggable">
208
Drag me down!
209
</div>
210
</div>
211
<div class="item dropzone"></div>
212
<div class="item dropzone"></div>
213
<div class="item dropzone"></div>
214
</div>
215
216
</div>
217
218
<script>
219
220
// Usage example:
221
222
/*
223
var workspace = document.querySelector('.workspace');
224
225
var dragger = new Dragger(workspace);
226
227
dragger.addDropzone(workspace.querySelector('.dropzone-1')); // place to put item
228
dragger.addDropzone(workspace.querySelector('.dropzone-2')); // place to put item
229
dragger.addDropzone(workspace.querySelector('.dropzone-3')); // place to put item
230
dragger.addDropzone(workspace.querySelector('.dropzone-4')); // place to put item
231
232
dragger.addDraggable(workspace.querySelector('.draggable-1')); // draggable item
233
dragger.addDraggable(workspace.querySelector('.draggable-2')); // draggable item
234
235
dragger.enable();
236
*/
237
238
//NOTE: Below code lets' to enable items dragging on all detected workspaces.
239
240
function prepareDropzones(dragger, workspace) {
241
var dropzones = workspace.querySelectorAll('.dropzone');
242
for (var j = 0; j < dropzones.length; ++j) {
243
dragger.addDropzone(dropzones[j]);
244
}
245
}
246
247
function prepareDraggables(dragger, workspace) {
248
var draggables = workspace.querySelectorAll('.draggable');
249
for (var j = 0; j < draggables.length; ++j) {
250
dragger.addDraggable(draggables[j]);
251
}
252
}
253
254
function prepareWorkspace(workspace) {
255
var dragger = new Dragger(workspace);
256
prepareDropzones(dragger, workspace);
257
prepareDraggables(dragger, workspace);
258
dragger.enable();
259
}
260
261
function prepareWorkspaces() {
262
var workspaces = document.querySelectorAll('.workspace');
263
for (var i = 0; i < workspaces.length; ++i) {
264
prepareWorkspace(workspaces[i])
265
}
266
}
267
268
prepareWorkspaces();
269
270
</script>
271
</body>
272
</html>