Search code examples
javascripthtmlcss

Put text under drag-n-drop area


I'm trying to help my users make choices by adding some tips in the form of text "underneath" the drop areas in my script. This causes the draggable button to lock in underneath the text and look plain ol' ugly.

In my example here the draggable button fits OK in "Box 3", but what can I do to make it fit the same way (and hide the tip) in "Box 2"?

And, imagine that the buttons have different values (numbers that is). How would I go about writing a script that adds these values and prints them out in "Summary"?

The values are not present in the text inside the button. To be honest - I don't really know where to put the values. I guess I could do a "massive" if-else and add a certain value if the innerHTML equals bla bla - but that seems very childlish...

And please, Vanilla only - I'm trying to learn this right.

var dropTarget = document.querySelectorAll(".wrapper");
var draggables = document.querySelectorAll(".button");

// Legger til en eventlistener på alle knappene
for (let i = 0; i < draggables.length; i++) {
  draggables[i].addEventListener("dragstart", function(ev) {
    ev.dataTransfer.setData("srcID", ev.target.id);
  });
}

for (let i = 0; i < dropTarget.length; i++) {
  dropTarget[i].addEventListener("dragover", function(ev) {
    ev.preventDefault();
  });

  dropTarget[i].addEventListener("drop", function(ev) {
    ev.preventDefault();
    let target = ev.target;
    let srcID = ev.dataTransfer.getData("srcID");

    let droppable = target.classList.contains("wrapper");

    if (droppable) {
      target.appendChild(document.getElementById(srcID));
    }
  });
}
.bord-box {
  margin: 0px;
  height: 100px;
  width: 100px;
  padding: 5px;
  border: solid 1px grey;
  border-radius: 5px;
}

.box1 {
  margin: 0px;
  height: 100px;
  width: 100px;
  padding: 5px;
  border: solid 1px grey;
}

.box2 {
  margin: 0px;
  height: 100px;
  width: 100px;
  padding: 5px;
  border: solid 1px red;
}

.button {
  margin: 5px 0 5px 0;
  border: solid 1px grey;
  height: 30px;
  width: 90px;
}

.mottak {
  height: 40px;
  background-color: grey;
}
<div class="section">
  <div class="column" style="position:absolute; top:50px;">
    <p>Box 1</p>
    <div class="bord-box wrapper">
      <button id="value1" class="button" draggable="true">Text 1</button>
      <button id="value2" class="button" draggable="true">Text 2</button>
    </div>
  </div>
  <div class="column" style="position:absolute; left:200px; top:50px;">
    <p>Box 2</p>
    <div class="box1">
      <div class="mottak wrapper">
        Move button here ...
      </div>
    </div>
  </div>
  <div class="column" style="position:absolute; left:400px; top:50px;">
    <p>Box 3</p>
    <div class="box2">
      <div class="mottak wrapper">
      </div>
    </div>
  </div>
  <div class="column" style="position:absolute; left:600px; top:50px;">
    <p>Summary</p>
    <div class="box1">
      <p>Sum value of buttons Text 1 and Text 2</p>
    </div>
  </div>


Solution

  • Here is a simple quick fix just by adding a pseudo class to the .mottak elements. However, please note there can't be any whitespace in the elements for :empty to work.

    .mottak:empty::before essentially only add's the content property to that element if it is empty (has no children)

    var dropTarget = document.querySelectorAll(".wrapper");
    var draggables = document.querySelectorAll(".button");
    
    // Legger til en eventlistener på alle knappene
    for (let i = 0; i < draggables.length; i++) {
      draggables[i].addEventListener("dragstart", function(ev) {
        ev.dataTransfer.setData("srcID", ev.target.id);
      });
    }
    
    for (let i = 0; i < dropTarget.length; i++) {
      dropTarget[i].addEventListener("dragover", function(ev) {
        ev.preventDefault();
      });
    
      dropTarget[i].addEventListener("drop", function(ev) {
        ev.preventDefault();
        let target = ev.target;
        let srcID = ev.dataTransfer.getData("srcID");
    
        let droppable = target.classList.contains("wrapper");
    
        if (droppable) {
          target.appendChild(document.getElementById(srcID));
        }
      });
    }
    /** added */
    
    .mottak:empty::before {
      content: "Move button here...";
    }
    
    /* end of edit */
    
    .bord-box {
      margin: 0px;
      height: 100px;
      width: 100px;
      padding: 5px;
      border: solid 1px grey;
      border-radius: 5px;
    }
    
    .box1 {
      margin: 0px;
      height: 100px;
      width: 100px;
      padding: 5px;
      border: solid 1px grey;
    }
    
    .box2 {
      margin: 0px;
      height: 100px;
      width: 100px;
      padding: 5px;
      border: solid 1px red;
    }
    
    .button {
      margin: 5px 0 5px 0;
      border: solid 1px grey;
      height: 30px;
      width: 90px;
    }
    
    .mottak {
      height: 40px;
      background-color: grey;
    }
    <div class="section">
      <div class="column" style="position:absolute; top:50px;">
        <p>Box 1</p>
        <div class="bord-box wrapper">
          <button id="value1" class="button" draggable="true">Text 1</button>
          <button id="value2" class="button" draggable="true">Text 2</button>
        </div>
      </div>
      <div class="column" style="position:absolute; left:200px; top:50px;">
        <p>Box 2</p>
        <div class="box1">
          <div class="mottak wrapper"></div>
        </div>
      </div>
      <div class="column" style="position:absolute; left:400px; top:50px;">
        <p>Box 3</p>
        <div class="box2">
          <div class="mottak wrapper"></div>
        </div>
      </div>
      <div class="column" style="position:absolute; left:600px; top:50px;">
        <p>Summary</p>
        <div class="box1">
          <p>Sum value of buttons Text 1 and Text 2</p>
        </div>
      </div>