Drag 'n Drop Multiple DIVs

Thanks ,
I am trying to turn a ‘Drag & Drop Single Div code’ into ‘DnD Multiple Divs code’ .
I like the ‘Single DnD Div Code’ very much because it is very fast .

The ‘who clicked me’ part works fine .

<script>
var e ;
var elmnt ;
var eventHold ;
var holdTargetId ;
var holdTarget ;
var theParent = document.querySelector("#elemContainer");
theParent.addEventListener("click", whoClickedMe, false);
function whoClickedMe(e) {
    if (e.target !== e.currentTarget) {
        var holdTarget = e.target.id;
        alert("He did = " + holdTarget);
	dragElement() ;		
    }
    e.stopPropagation();
}
</script>

But I’m stuck on the DnD part , how to call ‘function dragElement()’ , etc. .
Here is the original code: (and below that is the current Problem code .)

<!DOCTYPE html>
<html>
<style>
#mydiv {
  position: absolute;
  z-index: 9;
  background-color: #f1f1f1;
  text-align: center;
  border: 1px solid #d3d3d3;
}
#mydivheader {
  padding: 10px;
  cursor: move;
  z-index: 10;
  background-color: #2196F3;
  color: #fff;
}
</style>
<body>
<h1>Draggable DIV Element</h1>
<p>Click and hold the mouse button down while moving the DIV element</p>
<div id="mydiv">
  <div id="mydivheader">Click here to move</div>
  <p>Move</p>
  <p>this</p>
  <p>DIV</p>
</div>
<script>
//Make the DIV element draggagle:
dragElement(document.getElementById("mydiv"));
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;
  }
}
</script>
</body>
</html>

Here is the problem code:
Here are the Errors:

Uncaught TypeError: Cannot set properties of undefined (setting 'onmousedown') at dragElement (DnD-Multiple-DIVs.html:66:22) at HTMLDivElement.whoClickedMe

// line# 52: dragElement() ;
// line# 66 elmnt.onmousedown = dragMouseDown;

<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<style>
img {
    margin: 5px;
    padding: 5px 8px;
    outline: none;
    border: none;
    color: white;
    font-size: 1em;
}

div:hover {
//    background-color: #ffa000;
    cursor: pointer;
}

#result {
  border:1px solid; 
  display:inline-block;
  margin:5px;
/*   padding:5px; */
}
</style>
</head>
<body>

<div id="elemContainer" style="position: absolute;  width: 1420px; height: 750px;  display:inline-block; ">

  <div class="item" id="elem1" draggable="true" style="border-radius: 50%; width:32px; height:32px; position: relative; float:left; left: 30%; top:0; background-color: #FF0004;">&nbsp;1</div>
 
 <div class="item" id="elem2" draggable="true" style="border-radius: 50%; width:32px; height:32px; position: relative; float:left; left: 31%;  top: 0; background-color: #FE8E05;">&nbsp;2</div>
 
 </div>  <!--   id="elemContainer"  -->

<div id="result">result = </div>

<script>
var e ;
var elmnt ;
var eventHold ;
var holdTargetId ;
var holdTarget ;

var theParent = document.querySelector("#elemContainer");
theParent.addEventListener("click", whoClickedMe, false);
 
function whoClickedMe(e) {
    if (e.target !== e.currentTarget) {
        var holdTarget = e.target.id;
        alert("He did = " + holdTarget);
	dragElement() ;		
    }
    e.stopPropagation();
}
</script>

<script>
function dragElement() {
console.log("function dragElement(holdTarget = "  + holdTargetId) ;
  elmnt = holdTarget ;

//  var savedTargetId = event.target.id ;
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;

   elmnt.onmousedown = dragMouseDown;  
}

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
	
console.log("function dragMouseDown(e)") ;

    // 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();
//console.log("function elementDrag(e)") ;

    // 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:*/
//console.log("function closeDragElement()")
    document.onmouseup = null;
    document.onmousemove = null;
  }
</script>

</body></html>

Thank you for your Help.

Until someone more knowledgeable in JS comes along I modified the original code to move multiple elements by using a class instead of ids.

It might be of use. (Hopefully an expert will be passing by soon :))

1 Like

“Expert” (I’m not an expert) opinion: “Assa mess.”

Just so i’m clear on the requirements… when you say “Drag 'n Drop Multiple DIVs”… do you mean you want to move them all as a group? or be able to move individual ones, but have multiple of them on the page?

1 Like

Hi [m_hutley] ,
I mean to move each one separately .
As I get smarter Next step for me is to Create new div’s ,
probably between 20 - 30 .
Thanks

Thanks PaulOB ,
Yes , that works .
As I get smarter , Next step for me is to Create new div’s dynamically , possibly between 20 - 30 . I suspect that will require
running this for each Create-div:

const els = document.querySelectorAll(“.item”);
els.forEach((name) => {
console.log("els.forEach = " + name) ;
dragElement(name);
});

I have modified my code to be just like yours , see below ,
But prob right now is that whenever I try to Drag elem2
it gets positioned down a bit and to the right-most of page .
elem1 works fine .
I have compared your code with my copied code ,
but I can’t find the error .
Please , I need another set of eyes to take a look .
Thanks for your Help .


<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<style>
.elem1 .elem2 {

}

div:hover {
//    background-color: #ffa000;
    cursor: pointer;
}

#result {
  border:1px solid;
  display:inline-block;
  margin:5px;
/*   padding:5px; */
}
</style>
</head>
<body>

<div id="elemContainer" style="position: absolute;  width: 1420px; height: 750px;  display:inline-block; ">

  <div class="item elem1" draggable="true" style="border-radius: 50%; width:32px; height:32px; position: relative; float:left; left: 30%; top:0; background-color: #FF0004;">&nbsp;1</div>
 
 <div class="item elem2" draggable="true" style="border-radius: 50%; width:32px; height:32px; position: relative; float:left; left: 31%;  top: 0; background-color: #FE8E05;">&nbsp;2</div>
 
 </div>  <!--   id="elemContainer"  -->

<div id="result">result = </div>

<script>
var e ;
var elmnt ;
var eventHold ;
var holdTargetId ;
var holdTarget ;


const els = document.querySelectorAll(".item");
els.forEach((name) => {
console.log("els.forEach = " + name) ;
  dragElement(name);
});

function dragElement(elmnt) {
console.log("function dragElement() = "  + elmnt) ;
//  var savedTargetId = event.target.id ;
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;

   elmnt.onmousedown = dragMouseDown;
//}

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    
console.log("function dragMouseDown(e)") ;

    // 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();
//console.log("function elementDrag(e)") ;

    // 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:*/
console.log("function closeDragElement()")
    document.onmouseup = null;
    document.onmousemove = null;
  }
}
</script>

</body></html> 

I notice that ok/legal to Link to Codepen page .
I would like to Link to my webPage where I show both versions , Paul’s and my code , side by side , for comparison ,
**Is that ok/legal on this Forum? **
In the mean time , here are the CodePens:
https://codepen.io/paulobrien/embed/YzjbRWB?
https://codepen.io/Millie2/pen/gOjVKev

Thanks

In my code I used position:absolute for the drag items but you changed it back to relative which doesn’t make sense in that context. A relative element is never actually moved anywhere as it always occupies its original space in the flow even though it appears somewhere else.

As you are moving elements around it would seem that absolute positioning is required.

If you wanted to use relative positioning then 'I think’ you’d need to keep track of all the positions independently which isn’t required for the absolute element as it is just moved to where you want. That’s why only your first relative element is being moved correctly as its the only one that has its position remembered (if i understand the code correctly).

Also avoid inling your styles especially in demos as that make it ten times harder to change and test.

Thank you very much Paul .
I watched a couple videos on youtube on ‘console debugging’ and it all looked good . I think I would never have figure it out using that method .

Also avoid inling your styles especially in demos as that make it ten times harder to change and test.

Ok , will do .
So now I’m off to study up on ‘relative vs absolute’ positioning .
Thanks

I always use the HTML Drag and Drop API for moving things around the page. Google “js drag and drop tutorial” and get over 12,000,000 results.
Sitepoint had an excellent drag and drop tutorial several years ago.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.