full release edit capabilities oh my goodness gracious
Signed-off-by: ari melody <ari@arimelody.me>
This commit is contained in:
parent
34cddcfdb2
commit
604e2a4a7c
25 changed files with 1043 additions and 202 deletions
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Creates a "magic" reorderable list from `container`.
|
||||
* This function is absolute magic and I love it
|
||||
*
|
||||
* Example:
|
||||
* ```html
|
||||
* <ul id="list">
|
||||
* <li>Item 1</li>
|
||||
* <li>Item 2</li>
|
||||
* <li>Item 3</li>
|
||||
* </ul>
|
||||
* ```
|
||||
* ```js
|
||||
* // javascript
|
||||
* makeMagicList(document.getElementById("list"), "li");
|
||||
* ```
|
||||
*
|
||||
* @param {HTMLElement} container The parent container to use as a list.
|
||||
* @param {string} itemSelector The selector name of list item elements.
|
||||
* @param {Function} callback A function to call after each reordering.
|
||||
*/
|
||||
export function makeMagicList(container, itemSelector, callback) {
|
||||
if (!container)
|
||||
throw new Error("container not provided");
|
||||
if (!itemSelector)
|
||||
throw new Error("itemSelector not provided");
|
||||
|
||||
container.querySelectorAll(itemSelector).forEach(item => {
|
||||
item.draggable = true;
|
||||
item.addEventListener("dragstart", () => { item.classList.add("moving") });
|
||||
item.addEventListener("dragend", () => { item.classList.remove("moving") });
|
||||
item.querySelectorAll("input").forEach(el => {
|
||||
el.addEventListener("mousedown", () => { item.draggable = false });
|
||||
el.addEventListener("mouseup", () => { item.draggable = true });
|
||||
el.addEventListener("dragstart", e => { e.stopPropagation() });
|
||||
});
|
||||
});
|
||||
|
||||
var lastCursorY;
|
||||
container.addEventListener("dragover", event => {
|
||||
const dragging = container.querySelector(itemSelector + ".moving");
|
||||
if (!dragging) return;
|
||||
|
||||
let cursorY = event.touches ? event.touches[0].clientY : event.clientY;
|
||||
|
||||
// don't bother processing if we haven't moved
|
||||
if (lastCursorY === cursorY) return
|
||||
lastCursorY = cursorY;
|
||||
|
||||
// get the element positioned ahead of the cursor
|
||||
const notMoving = [...container.querySelectorAll(itemSelector + ":not(.moving)")];
|
||||
const afterElement = notMoving.reduce((previous, current) => {
|
||||
const box = current.getBoundingClientRect();
|
||||
const offset = cursorY - box.top - box.height / 2;
|
||||
if (offset < 0 && offset > previous.offset)
|
||||
return { offset: offset, element: current };
|
||||
return previous;
|
||||
}, { offset: Number.NEGATIVE_INFINITY }).element;
|
||||
|
||||
if (afterElement) {
|
||||
container.insertBefore(dragging, afterElement);
|
||||
} else {
|
||||
container.appendChild(dragging);
|
||||
}
|
||||
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue