TIL-js

πŸ“™ Tutorial : How To Build Sortable Drag & Drop With Vanilla Javascript

예제 λ°”λ‘œκ°€κΈ°


<!-- html λ¬Έμ„œ -->

<section class="container">
  <div class="draggable" draggable="true">
    <span class="text">솑인</span>
    <i class="fas fa-bars"></i>
  </div>
  <div class="draggable" draggable="true">
    <span class="text">무심세월</span>
    <i class="fas fa-bars"></i>
  </div>
  <div class="draggable" draggable="true">
    <span class="text">회초리</span>
    <i class="fas fa-bars"></i>
  </div>
  <div class="draggable" draggable="true">
    <span class="text">μ„œμšΈ κ°€ μ‚΄μž</span>
    <i class="fas fa-bars"></i>
  </div>
  <div class="draggable" draggable="true">
    <span class="text">μ΄λ³„νŽΈμ§€</span>
    <i class="fas fa-bars"></i>
  </div>
  <div class="draggable" draggable="true">
    <span class="text">κ°€μ‹œμ˜€</span>
    <i class="fas fa-bars"></i>
  </div>
</section>


// js 파일

const draggables = document.querySelectorAll(".draggable");

draggables.forEach((draggable) => {
  draggable.addEventListener("dragstart", () => {
    draggable.classList.add("dragging");
  });

  draggable.addEventListener("dragend", () => {
    draggable.classList.remove("dragging");
  });
});


container.addEventListener("dragover", (e) => {
  e.preventDefault();

  const draggable = document.querySelector(".dragging");
  const afterElement = getDragAfterElement(container, e.clientY);

  container.insertBefore(draggable, afterElement);
});


function getDragAfterElement(container, y) {
  const draggableElements = [
    ...container.querySelectorAll(".draggable:not(.dragging)"),
  ];

  return draggableElements.reduce(
    (closest, child) => {
      const box = child.getBoundingClientRect();
      const offset = y - box.top - box.height / 2;
      if (offset < 0 && offset > closest.offset) {
        return { offset: offset, element: child };
      } else {
        return closest;
      }
    },
    { offset: Number.NEGATIVE_INFINITY }
  ).element;
}


container.addEventListener("drop", () => {
  const correctArray = [
    "회초리",
    "무심세월",
    "솑인",
    "κ°€μ‹œμ˜€",
    "μ΄λ³„νŽΈμ§€",
    "μ„œμšΈ κ°€ μ‚΄μž",
  ];

  const draggables = container.querySelectorAll(".draggable");
  const currentArray = [...draggables].map((draggable) => draggable.innerText);

  const equals = (a, b) => JSON.stringify(a) === JSON.stringify(b);

  if (equals(correctArray, currentArray)) {
    container.style.backgroundColor = "lavenderblush";
    alert("μ •λ‹΅μž…λ‹ˆλ‹€πŸ’œ");
  }
});