From 1330f230c4b349d0920cffaabeb8fb8652a8739c Mon Sep 17 00:00:00 2001 From: Adrian Gruntkowski Date: Mon, 11 Nov 2024 20:30:03 +0100 Subject: [PATCH] Implement basic desktop drag and drop --- index.html | 7 +++---- js/jenot.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ style.css | 4 ++++ 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 0987eb8..fd922ff 100644 --- a/index.html +++ b/index.html @@ -23,6 +23,7 @@ href="/img/favicon-16x16.png" /> + @@ -36,8 +37,8 @@
    -
  • one
  • -
  • two
  • +
  • one
  • +
  • two
@@ -49,7 +50,5 @@
- - diff --git a/js/jenot.js b/js/jenot.js index deaa16b..0ccbf07 100644 --- a/js/jenot.js +++ b/js/jenot.js @@ -151,9 +151,24 @@ class TaskListItem extends HTMLElement { } }); + // drag and drop events + + this.parentNode.addEventListener("dragstart", (e) => { + this.parentNode.classList.add("dragging"); + }); + + this.parentNode.addEventListener("dragend", () => { + this.parentNode.classList.remove("dragging"); + }); + this.#updateChecked(); } + disconnectedCallback() { + this.textContent = this.contentElement.value; + this.setAttribute("checked", this.checkboxElement.checked); + } + attributeChangedCallback(name, oldValue, newValue) { if (name === "checked") { this.#updateChecked(); @@ -195,11 +210,14 @@ class TaskList extends HTMLElement { } connectedCallback() { + this.listElement = this.querySelector("ul"); + this.addEventListener("removeTaskWithButton", (e) => { const tasksCount = this.querySelectorAll("task-list-item").length; if (tasksCount === 1) { const newLI = document.createElement("li"); + newLI.setAttribute("draggable", "true"); const newItem = document.createElement("task-list-item"); newLI.appendChild(newItem); this.querySelector("ul").appendChild(newLI); @@ -228,6 +246,7 @@ class TaskList extends HTMLElement { const currentLI = e.target.parentNode; const newLI = document.createElement("li"); + newLI.setAttribute("draggable", "true"); const newItem = document.createElement("task-list-item"); newItem.textContent = text; newLI.appendChild(newItem); @@ -254,6 +273,40 @@ class TaskList extends HTMLElement { prevItem.focusEnd(); } }); + + // drag and drop + this.listElement.addEventListener("dragover", (e) => { + e.preventDefault(); + + const afterElement = this.#getDragAfterElement(e.clientY); + const draggable = document.querySelector(".dragging"); + + if (afterElement == null) { + this.listElement.appendChild(draggable); + } else { + this.listElement.insertBefore(draggable, afterElement); + } + }); + } + + #getDragAfterElement(y) { + const draggableElements = [ + ...this.listElement.querySelectorAll("li:not(.dragging)"), + ]; + + return draggableElements.reduce( + (closest, containerChild) => { + const box = containerChild.getBoundingClientRect(); + const offset = y - box.top - box.height / 2; + + if (offset < 0 && offset > closest.offset) { + return { offset: offset, element: containerChild }; + } else { + return closest; + } + }, + { offset: Number.NEGATIVE_INFINITY }, + ).element; } } diff --git a/style.css b/style.css index 175a0b0..082376b 100644 --- a/style.css +++ b/style.css @@ -128,6 +128,10 @@ task-list-item .checkbox input { height: 1.1em; } +.dragging { + opacity: 0.5; +} + /* Styles */ * {