EN
JavaScript - drag and drop div
5 points
Using JavaScript it is possible to make drag&drop div element in following way.
Note: big advantage of presented approach in this section is resistance for changed margin, border and padding sizes (with nested elements too).
More complicated example with handle element is here.
xxxxxxxxxx
1
2
<html>
3
<head>
4
<style>
5
6
div.draggable {
7
padding: 10px;
8
position: absolute;
9
left: 20px; right: 20px;
10
background: gray;
11
width: 150px; height: 150px;
12
/* this style disables elements selection when user is dragging */
13
touch-callout: none; /* iOS Safari */
14
user-select: none; /* Safari */
15
user-select: none; /* Konqueror HTML */
16
user-select: none; /* Firefox in the past (old versions) */
17
user-select: none; /* Internet Explorer (>=10) / Edge */
18
user-select: none; /* Currently supported: */
19
/* Chrome, Opera and Firefox */
20
}
21
22
</style>
23
<script type="text/javascript">
24
25
function computeMargins(element) {
26
var style = element.currentStyle || window.getComputedStyle(element);
27
var result = {
28
marginLeft: parseInt(style.marginLeft),
29
marginRight: parseInt(style.marginRight),
30
marginTop: parseInt(style.marginTop),
31
marginBottom: parseInt(style.marginBottom)
32
};
33
return result;
34
}
35
36
function computeMargins(element) {
37
var style = element.currentStyle || window.getComputedStyle(element);
38
var result = {
39
marginLeft: parseInt(style.marginLeft),
40
marginRight: parseInt(style.marginRight),
41
marginTop: parseInt(style.marginTop),
42
marginBottom: parseInt(style.marginBottom)
43
};
44
return result;
45
}
46
47
function prepareDragging(element) {
48
var removed = false;
49
var dragging = false;
50
var style = element.style;
51
var clickX, clickY, positionX, positionY;
52
var onMouseDown = function(e) {
53
clickX = e.clientX;
54
clickY = e.clientY;
55
var margins = computeMargins(element);
56
// this approach prevents against dragging issues when margins have set sizes
57
positionX = element.offsetLeft - margins.marginLeft - margins.marginRight;
58
positionY = element.offsetTop - margins.marginTop - margins.marginBottom;
59
dragging = true;
60
};
61
var onMouseUp = function(e) {
62
dragging = false;
63
};
64
var onMouseMove = function(e) {
65
if (dragging) {
66
var x = positionX + e.clientX - clickX;
67
var y = positionY + e.clientY - clickY;
68
style.left = x + 'px';
69
style.top = y + 'px';
70
}
71
};
72
var onTouchStart = function(event) {
73
var touches = event.touches;
74
if (touches.length === 1) {
75
event.preventDefault();
76
var touch = touches[0];
77
onMouseDown({
78
clientX: touch.clientX,
79
clientY: touch.clientY
80
});
81
}
82
};
83
var onTouchEnd = function(event) {
84
var touches = event.touches;
85
if (touches.length === 0) {
86
onMouseUp({});
87
}
88
};
89
var onTouchMove = function(event) {
90
if (dragging) {
91
event.preventDefault();
92
var touches = event.touches;
93
if (touches.length === 1) {
94
var touch = touches[0];
95
onMouseMove({
96
clientX: touch.clientX,
97
clientY: touch.clientY
98
});
99
}
100
}
101
};
102
element.addEventListener('mousedown', onMouseDown);
103
element.addEventListener('touchstart', onTouchStart);
104
window.addEventListener('mouseup', onMouseUp);
105
window.addEventListener('touchend', onTouchEnd);
106
window.addEventListener('mousemove', onMouseMove);
107
window.addEventListener('touchmove', onTouchMove);
108
return function() {
109
if (removed) {
110
return;
111
}
112
element.removeEventListener('mousedown', onMouseDown);
113
element.removeEventListener('touchstart', onTouchStart);
114
window.removeEventListener('mouseup', onMouseUp);
115
window.removeEventListener('touchend', onTouchEnd);
116
window.removeEventListener('mousemove', onMouseMove);
117
window.removeEventListener('touchmove', onTouchMove);
118
removed = true;
119
};
120
}
121
122
</script>
123
</head>
124
<body style="height: 200px;">
125
<div id="my-element" class="draggable">
126
Something inside...
127
</div>
128
<script>
129
130
var element = document.querySelector('#my-element');
131
132
prepareDragging(element);
133
134
</script>
135
</body>
136
</html>