Welcome to Code Forum!

Join a community that supports you and your coding journey from day one. We strive to be a friendly, supportive community that empowers everyone to be better developers. By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.

    GIF shows where to locate </> in the thread and or post editor toolbar.
    To learn more about how to use our BBCode feature, review our "How to post your code into threads" here.

    Thank you, Code Forum.

JavaScript Need Help with Drag-n-Drop...

vmars316

Well-Known Coder
Hello & TIA ,
Need help , Having problem with Drag n Drop ?

My code seems quite simple , but I have been hung up for days :

The first DnD doesnt Drop : 'div id="itemContainer" ' , getting Errors:

Code:
Guitar-Scales-and-Boxes-Builder-4-Note-4-Frets-CLONE-MINIMAL.html:131 Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at drop (Guitar-Scales-and-Boxes-Builder-4-Note-4-Frets-CLONE-MINIMAL.html:131:16)
    at HTMLTableElement.ondrop (Guitar-Scales-and-Boxes-Builder-4-Note-4-Frets-CLONE-MINIMAL.html:78:132)

Tha 2nd DnD works fine .
Code:
<!DOCTYPE HTML>
<html>
<head>
<style>
#div1, #div2 {
  float: left;
  width: 100px;
  height: 35px;
  margin: 10px;
  padding: 10px;
  border: 1px solid black;
}
    .item {
      display: inline-block;
      border-radius: 50%;
      touch-action: none;
      user-select: none;
      counter-increment: itemCount;
      content: 'count' + itemCount;
      width: 32px;
      height: 32px;
      font-family: Arial, Helvetica, sans-serif;
      text-align:center;
      font-size:28px;
      z-index: 8;
    }
</style>
</head>
<body>
<h2>Drag and Drop</h2>
<br>
<div id="itemContainer"   id="dragItems"    ondrop="drop(event)"  ondragover="allowDrop(event)" class="POS"  style=" width:100%;  border: thick solid pink;"> 
<br>  <div class="item" class="flatOne"  id="flatOne"     draggable="true"   style="  background-color: yellow;" >b1</div>   
<br>  <div class="item" class="one"            draggable="true" ondragstart="drag(event)"  style="  background-color: #FF0004;" > 1</div>   
<br>  <div class="item" class="sharpOne"    draggable="true" ondragstart="drag(event)"  style="  background-color: yellow;" >♯1</div>   
<br>  <div class="item" class="naturalOne"  draggable="true" ondragstart="drag(event)"  style="  background-color: yellow;" >♮1</div>   
</div>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
  <img src="RedCircle.png" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br><br><br><br>
<br>
<div  ondrop="drop(event)" ondragover="allowDrop(event)"  style=" border: thick solid blue; width:100%; height: 200px;">
</div>
<script>
function allowDrop(ev) {
  ev.preventDefault();
//  console.log("function allowDrop(ev)")
}
function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
  console.log("function function drag(ev)")
}
function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
  console.log("function drop(ev)")
}
</script>
</body>
</html>
 
Solution
D
Wow, that is quite a story... bit OT here. Save that for a new thread.
Is this drag&drop issue solved now, as I believe it is ?
Thanks, got it. Your statement "first drop works, second drop doesn't" was neither clear or accurate ! What you should have written is "Drag an drop of the red circle works, but drag and drop of any of the four small elements doesn't". It would have saved you having to make a video 😉

It wasn't hard to see why it didn't work. For an element to be droppable, it must have an id, and it must pass this id to the event in the drag() function. Now look at your 4 small round elements. This first has an id but no ondragstart(), the other three do have the ondragstart() but no id ! So the drop() function tries to drop null, and you get the error. If you correct that, it will work.

This issue could IMO have been avoided if:
  • You were more strict and conscious in assigning id and class attributes. Some elements have duplicate id's (which is an error), some have a class that isn't in the CSS (which is pointless). Some have a class that probably was meant to be an id. A class is fine for defining style, but to uniquely identify an element you really need an id (just the one 😁 ).
  • Your HTML code was cleaner and thus easier to read. For example, had you neatly tabulated the definition of these four small elements, you might well have seen there were things missing.
  • You had validated your code in the https://validator.w3.org/ online HTML validator. This warns you about the duplicate id's, for example, which might have set you thinking.
 
cbreemer Thank you very much...

Ah yes , id="" .
Originally , I used this code:

Code:
<script>
    var container = document.querySelector("#itemContainer");
    var activeItem = null;


    var active = false;


    container.addEventListener("touchstart", dragStart, false);
    container.addEventListener("touchend", dragEnd, false);
    container.addEventListener("touchmove", drag, false);


    container.addEventListener("mousedown", dragStart, false);
    container.addEventListener("mouseup", dragEnd, false);
    container.addEventListener("mousemove", drag, false);


    function dragStart(e) {


      if (e.target !== e.currentTarget) {
        active = true;


        // this is the item we are interacting with
        activeItem = e.target;


        if (activeItem !== null) {
          if (!activeItem.xOffset) {
            activeItem.xOffset = 0;
          }


          if (!activeItem.yOffset) {
            activeItem.yOffset = 0;
          }


          if (e.type === "touchstart") {
            activeItem.initialX = e.touches[0].clientX - activeItem.xOffset;
            activeItem.initialY = e.touches[0].clientY - activeItem.yOffset;
          } else {
            console.log("Dragging something!");
            activeItem.initialX = e.clientX - activeItem.xOffset;
            activeItem.initialY = e.clientY - activeItem.yOffset;
          }
        }
      }
    }


    function dragEnd(e) {
      if (activeItem !== null) {
        activeItem.initialX = activeItem.currentX;
        activeItem.initialY = activeItem.currentY;
      }


      active = false;
      activeItem = null;
    }


    function drag(e) {
      if (active) {
        if (e.type === "touchmove") {
          e.preventDefault();


          activeItem.currentX = e.touches[0].clientX - activeItem.initialX;
          activeItem.currentY = e.touches[0].clientY - activeItem.initialY;
        } else {
          activeItem.currentX = e.clientX - activeItem.initialX;
          activeItem.currentY = e.clientY - activeItem.initialY;
        }


        activeItem.xOffset = activeItem.currentX;
        activeItem.yOffset = activeItem.currentY;


        setTranslate(activeItem.currentX, activeItem.currentY, activeItem);
      }
    }


    function setTranslate(xPos, yPos, el) {
      el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
    }
  </script>

But the Cursor keeps loosing the Target , as you can view here ,
https://vmars.us/Guitar/Guitar-Scales-and-Boxes-Builder-1-Note-4-Frets-FORUM.html ;
Forcing me to keep going back and Grabbing Target again & again .
Which forces me to Drag at a sloth's pace .
Otherwise it works fine for class= .

So I was trying to find a better/FASTER solution , as in RedDot code above ;
unfortunately , I forgot the id= business .

Why not use id= as in here :
https://vmars.us/Guitar/Guitar-Scales-and-Boxes-Builder.html
If you view the html source , you will see that every .item has 6-duplicates ;
which turns out to be 7 x 7 = 49 .items .
So if I use id= I'll have to code 49 unique id='s .

So , I plan to Post a new thread , asking 'For a.js vs b.js , why is a.js so much Faster than b.js ? ' .
Faster meaning , "NOT Grabbing Target again & again " .
Sound reasonable ?

Thanks for your Help...
 

Buy us a coffee!

Buy me a coffee.
Back
Top Bottom