I want to have multiple divs on my website to be draggable and movable across the website (or at least in the container which it's found).
I would like to clarify that I searched on the web and Stackoverflow multiple times, but all of them suggest answers by using jQuery or some other libraries. I would like a pure JavaScript way of moving multiple divs (hopefully with just one function for all) across the website.
The project that I'm making is to practice drag and drop with HTML and JS, I have 4 divs in a container 'x' (with images in them) and another container 'y' to drag and drop those divs to that container 'y', but if I drag them all there, the first div just sets to the top left corner and the rest under them (or beside each other if I set their display to inline-block). So, I want to make those divs movable on that container 'y' which I dragged into to move them around wherever I need. (They are also resizable).
The Drag and drop JavaScript and HTML code (Excluding CSS and some unnecessary HTML code) is this:
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
ev.dataTransfer.dropEffect = "move";
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
<div id="images-container" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="resize" style="background: url('images/photo-1.jpg') center no-repeat; background-size: cover; background-position: center center;" id="drag1" draggable="true" ondragstart="drag(event)">
</div>
<div class="resize" style="background: url('images/photo-2.jpg') center no-repeat; background-size: cover; background-position: center center;" id="drag2" draggable="true" ondragstart="drag(event)">
</div>
<div class="resize" style="background: url('images/photo-3.jpg') center no-repeat; background-size: cover; background-position: center center;" id="drag3" draggable="true" ondragstart="drag(event)">
</div>
<div class="resize" style="background: url('images/photo-4.jpg') center no-repeat; background-size: cover; background-position: center center;" id="drag4" draggable="true" ondragstart="drag(event)">
</div>
</div>
<div id="gallery" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
I want to have multiple divs on my website to be draggable and movable across the website (or at least in the container which it's found).
I would like to clarify that I searched on the web and Stackoverflow multiple times, but all of them suggest answers by using jQuery or some other libraries. I would like a pure JavaScript way of moving multiple divs (hopefully with just one function for all) across the website.
The project that I'm making is to practice drag and drop with HTML and JS, I have 4 divs in a container 'x' (with images in them) and another container 'y' to drag and drop those divs to that container 'y', but if I drag them all there, the first div just sets to the top left corner and the rest under them (or beside each other if I set their display to inline-block). So, I want to make those divs movable on that container 'y' which I dragged into to move them around wherever I need. (They are also resizable).
The Drag and drop JavaScript and HTML code (Excluding CSS and some unnecessary HTML code) is this:
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
ev.dataTransfer.dropEffect = "move";
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
<div id="images-container" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="resize" style="background: url('images/photo-1.jpg') center no-repeat; background-size: cover; background-position: center center;" id="drag1" draggable="true" ondragstart="drag(event)">
</div>
<div class="resize" style="background: url('images/photo-2.jpg') center no-repeat; background-size: cover; background-position: center center;" id="drag2" draggable="true" ondragstart="drag(event)">
</div>
<div class="resize" style="background: url('images/photo-3.jpg') center no-repeat; background-size: cover; background-position: center center;" id="drag3" draggable="true" ondragstart="drag(event)">
</div>
<div class="resize" style="background: url('images/photo-4.jpg') center no-repeat; background-size: cover; background-position: center center;" id="drag4" draggable="true" ondragstart="drag(event)">
</div>
</div>
<div id="gallery" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
I checked this article by W3schools, but it works with just one div element, as it's built with an ID, but what can I do with this code to use it for multiple divs and with classes I guess? If there is another way of doing it, I'll be glad to hear some suggestions about it, though in pure JavaScript.
Thanks.
Share Improve this question asked Jul 18, 2018 at 19:26 kkasbariankkasbarian 411 gold badge2 silver badges10 bronze badges 2- You answered your own question, here you have working example how to do this: w3schools./howto/howto_js_draggable.asp just add another div with different id – RainDev Commented Jul 18, 2018 at 20:20
- @Rainmx93 I know, I totally understand, but for that, I should have 4 functions for 4 different ID's, but I want to have one function for all the divs, maybe with the same classes or with query selectors, but I'm not sure how to change the function to work with classes given to the divs. Any suggestions will be appreciated. – kkasbarian Commented Jul 19, 2018 at 11:30
3 Answers
Reset to default 4This works for me. No JQuery used.
I produces 4 divs all on top of each other but they can be dragged around. When you click on a div, its border lights up and you can drag it. The dragged div moves in front of the other divs. Because it looks fun, I've drawn curves between the divs using a canvas.
<!doctype html>
<html>
<head>
<style>
div {
position: absolute;
top: 0;
height: 60px;
width: 100px;
background: #15a5ed;
text-align: center;
line-height: 60px;
border-radius: 15px 15px 15px 15px;
}
</style>
</head>
<body>
<canvas id="canvas" class="canvas"></canvas>
<div id="div1">Me</div>
<div id="div2">You</div>
<div id="div3">Us</div>
<div id="div4">Them</div>
<script>
divs = document.getElementsByTagName("div");
for (div of divs) div.onmousedown = onMouseDown;
document.onmousemove = onMouseMove;
document.onmouseup = onMouseUp;
canvas.width = window.innerWidth - 20;
canvas.height = window.innerHeight - 20;
var the_moving_div = '';
var the_last_mouse_position = { x:0, y:0 };
drawConnectors();
function onMouseDown(e) {
e.preventDefault();
the_moving_div = e.target.id; // remember which div has been selected
the_last_mouse_position.x = e.clientX; // remember where the mouse was when it was clicked
the_last_mouse_position.y = e.clientY;
e.target.style.border = "2px solid blue"; // highlight the border of the div
var divs = document.getElementsByTagName("div");
e.target.style.zIndex = divs.length; // put this div on top
var i = 1; for (div of divs) if (div.id != the_moving_div) div.style.zIndex = i++; // put all other divs behind the selected one
}
function onMouseMove(e) {
e.preventDefault();
if (the_moving_div == "") return;
var d = document.getElementById(the_moving_div);
d.style.left = d.offsetLeft + e.clientX - the_last_mouse_position.x + "px"; // move the div by however much the mouse moved
d.style.top = d.offsetTop + e.clientY - the_last_mouse_position.y + "px";
the_last_mouse_position.x = e.clientX; // remember where the mouse is now
the_last_mouse_position.y = e.clientY;
drawConnectors();
}
function onMouseUp(e) {
e.preventDefault();
if (the_moving_div == "") return;
document.getElementById(the_moving_div).style.border = "none"; // hide the border again
the_moving_div = "";
}
function drawConnectors() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.strokeStyle="#15a5ed";
ctx.lineWidth=3;
for (div1 of divs) for (div2 of divs) {
if (div1 == div2) continue;
ctx.moveTo(div1.offsetLeft + div1.clientWidth/2, div1.offsetTop + div1.clientHeight/2);
ctx.bezierCurveTo(div1.offsetLeft, div1.offsetTop,
div2.offsetLeft, div2.offsetTop,
div2.offsetLeft + div2.clientWidth/2, div2.offsetTop + div2.clientHeight/2);
ctx.stroke();
}
}
</script>
</body>
</html>
I guess you probably sorted this by now. I will post this here for people like me who are searching for the answer. I thought that w3Schools example would only work for a single element too. It actually works on multiple elements just by calling the function on each one.
var draggableElements = document.getElementsByClassName("draggable");
for(var i = 0; i < draggableElements.length; i++){
dragElement(draggableElements[i]);
}
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
} else {
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
pos3 = parseInt(e.clientX);
pos4 = parseInt(e.clientY);
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
return false;
}
function elementDrag(e) {
e = e || window.event;
pos1 = pos3 - parseInt(e.clientX);
pos2 = pos4 - parseInt(e.clientY);
pos3 = parseInt(e.clientX);
pos4 = parseInt(e.clientY);
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
console.log(elmnt.offsetTop)
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
}
}
Now at first this gave me odd results. My divs were only going in one direction when I moved the mouse, if you have margin on the divs it will mess up the calculations. So either don't use margin or edit the code to work for them.
Link to the original W3Schools tut: https://www.w3schools./howto/howto_js_draggable.asp
I have had a little play around with this. Using the w3 schools example. I have expanded on that to make it dynamic, (class selectable).
Here is the JavaScript to make it work.
document.addEventListener('DOMContentLoaded', function () {
//Make the DIV element draggagle:
members = document.querySelectorAll('.mover').forEach(item => {
item.addEventListener('mousedown', ev => {
console.log(ev);
let tid;
tid = ev.target.id;
if (ev.target.id == "") {
tid = ev.target.parentNode.id;
}
dragElement(document.getElementById(tid));
})
})
function dragElement(elmnt) {
var pos1 = 0,
pos2 = 0,
pos3 = 0,
pos4 = 0;
if (document.getElementById(elmnt.id + 'header')) {
/* if present, the header is where you move the DIV from:*/
document.getElementById(elmnt.id + 'header').onmousedown =
dragMouseDown;
} else {
/* otherwise, move the DIV from anywhere inside the DIV:*/
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.top = elmnt.offsetTop - pos2 + 'px';
elmnt.style.left = elmnt.offsetLeft - pos1 + 'px';
}
function closeDragElement() {
/* stop moving when mouse button is released:*/
document.onmouseup = null;
document.onmousemove = null;
}
}
});
Noting the changes I have made:
- DOM Lister wrapping the code.
- mousedown listener assigned to the class ".mover"