mirror of
https://github.com/zoldar/jenot.git
synced 2026-01-05 07:02:55 +00:00
Implement basic desktop drag and drop
This commit is contained in:
parent
ec2952c172
commit
1330f230c4
3 changed files with 60 additions and 4 deletions
|
|
@ -23,6 +23,7 @@
|
||||||
href="/img/favicon-16x16.png"
|
href="/img/favicon-16x16.png"
|
||||||
/>
|
/>
|
||||||
<link rel="manifest" href="/site.webmanifest" />
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
|
<script src="/js/jenot.js" defer></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -36,8 +37,8 @@
|
||||||
<div class="note">
|
<div class="note">
|
||||||
<task-list>
|
<task-list>
|
||||||
<ul>
|
<ul>
|
||||||
<li><task-list-item checked>one</task-list-item></li>
|
<li draggable="true"><task-list-item checked>one</task-list-item></li>
|
||||||
<li><task-list-item>two</task-list-item></li>
|
<li draggable="true"><task-list-item>two</task-list-item></li>
|
||||||
</ul>
|
</ul>
|
||||||
</task-list>
|
</task-list>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -49,7 +50,5 @@
|
||||||
<editable-area></editable-area>
|
<editable-area></editable-area>
|
||||||
<div class="remove"><button>X</button></div>
|
<div class="remove"><button>X</button></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="/js/jenot.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
53
js/jenot.js
53
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();
|
this.#updateChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
this.textContent = this.contentElement.value;
|
||||||
|
this.setAttribute("checked", this.checkboxElement.checked);
|
||||||
|
}
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
attributeChangedCallback(name, oldValue, newValue) {
|
||||||
if (name === "checked") {
|
if (name === "checked") {
|
||||||
this.#updateChecked();
|
this.#updateChecked();
|
||||||
|
|
@ -195,11 +210,14 @@ class TaskList extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
|
this.listElement = this.querySelector("ul");
|
||||||
|
|
||||||
this.addEventListener("removeTaskWithButton", (e) => {
|
this.addEventListener("removeTaskWithButton", (e) => {
|
||||||
const tasksCount = this.querySelectorAll("task-list-item").length;
|
const tasksCount = this.querySelectorAll("task-list-item").length;
|
||||||
|
|
||||||
if (tasksCount === 1) {
|
if (tasksCount === 1) {
|
||||||
const newLI = document.createElement("li");
|
const newLI = document.createElement("li");
|
||||||
|
newLI.setAttribute("draggable", "true");
|
||||||
const newItem = document.createElement("task-list-item");
|
const newItem = document.createElement("task-list-item");
|
||||||
newLI.appendChild(newItem);
|
newLI.appendChild(newItem);
|
||||||
this.querySelector("ul").appendChild(newLI);
|
this.querySelector("ul").appendChild(newLI);
|
||||||
|
|
@ -228,6 +246,7 @@ class TaskList extends HTMLElement {
|
||||||
const currentLI = e.target.parentNode;
|
const currentLI = e.target.parentNode;
|
||||||
|
|
||||||
const newLI = document.createElement("li");
|
const newLI = document.createElement("li");
|
||||||
|
newLI.setAttribute("draggable", "true");
|
||||||
const newItem = document.createElement("task-list-item");
|
const newItem = document.createElement("task-list-item");
|
||||||
newItem.textContent = text;
|
newItem.textContent = text;
|
||||||
newLI.appendChild(newItem);
|
newLI.appendChild(newItem);
|
||||||
|
|
@ -254,6 +273,40 @@ class TaskList extends HTMLElement {
|
||||||
prevItem.focusEnd();
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,10 @@ task-list-item .checkbox input {
|
||||||
height: 1.1em;
|
height: 1.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dragging {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
/* Styles */
|
/* Styles */
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue