Page MenuHomeSealhub

sortable.stimulus.ts
No OneTemporary

sortable.stimulus.ts

/* eslint-disable @typescript-eslint/no-for-in-array */
/* eslint-disable @typescript-eslint/consistent-type-assertions */
import { Controller } from "stimulus";
async function sleep(time: number) {
return new Promise((resolve) => {
setTimeout(resolve, time);
});
}
export default class Sortable extends Controller {
dragged_element: HTMLDivElement | null = null;
clearDoubleHoles() {
this.element
.querySelectorAll(".ready-to-drop")
.forEach((e: HTMLDivElement) => e.classList.remove("ready-to-drop"));
}
getNthElement(n: number): HTMLDivElement | null {
return this.element.querySelector(`.sortable__element:nth-child(${n})`);
}
setIndex(node: HTMLDivElement, index: number) {
node.setAttribute("data-index", String(index));
node.style.setProperty("--index", String(index));
}
setupHoleListeners(hole: HTMLDivElement) {
hole.addEventListener("dragenter", (event) => {
event.dataTransfer.dropEffect = "move";
if (!this.dragged_element) {
return;
}
(event.target as HTMLDivElement).classList.add("ready-to-drop");
event.preventDefault();
});
hole.addEventListener("dragover", (event) => {
event.dataTransfer.dropEffect = "move";
if (!this.dragged_element) {
return;
}
event.preventDefault();
});
hole.addEventListener("dragleave", (event) => {
(event.target as HTMLDivElement).classList.remove("ready-to-drop");
event.preventDefault();
});
hole.addEventListener("drop", (event) => {
const target = event.target as HTMLDivElement;
target.classList.remove("ready-to-drop");
const index_of_dropped_element = parseInt(
this.dragged_element.getAttribute("data-index")
);
const index_of_drop_target = parseInt(target.getAttribute("data-index"));
const nodes_of_dropped_element_index = this.element.querySelectorAll(
`[data-index="${index_of_dropped_element}"]`
);
const nodes_of_target_index = this.element.querySelectorAll(
`[data-index="${index_of_drop_target}"]`
);
let last_node_of_target_index =
nodes_of_target_index[nodes_of_target_index.length - 1];
for (const node of Array.from(nodes_of_dropped_element_index)) {
last_node_of_target_index.after(node);
this.setIndex(node as HTMLDivElement, index_of_drop_target);
last_node_of_target_index = node;
}
const next_to_correct = nodes_of_dropped_element_index[0].previousSibling;
const children = Array.from(next_to_correct.parentNode.childNodes);
const children_to_correct = children.slice(2);
for (const dom_index in children_to_correct) {
const index = Math.max(Math.floor(parseInt(dom_index) / 3), 0);
this.setIndex(children_to_correct[dom_index] as HTMLDivElement, index);
}
event.preventDefault();
});
}
connect() {
this.element.querySelectorAll(".sortable__element").forEach((element) => {
element.addEventListener("dragstart", (e: DragEvent) => {
e.dataTransfer.effectAllowed = "move";
const target = e.target as HTMLDivElement;
this.dragged_element = target;
setTimeout(() => {
// https://stackoverflow.com/a/20733870/1467284
target.classList.add("is-dragged");
}, 0);
});
element.addEventListener("dragend", (e: DragEvent) => {
const target = e.target as HTMLDivElement;
this.dragged_element = null;
target.classList.remove("is-dragged");
});
});
this.element
.querySelectorAll(".edge-detector")
.forEach((detector: HTMLDivElement) => {
let is_hovered = false;
detector.addEventListener("dragenter", (e) => {
e.preventDefault();
const target = e.target as HTMLDivElement;
const step = parseInt(target.getAttribute("data-step"));
is_hovered = true;
void (async () => {
while (is_hovered && this.dragged_element) {
window.scrollTo(window.scrollX, window.scrollY + step);
// eslint-disable-next-line no-await-in-loop
await sleep(16);
}
})();
});
detector.addEventListener("dragover ", (e) => {
// necessary for drag events;
e.preventDefault();
});
detector.addEventListener("dragleave", (e) => {
e.preventDefault();
is_hovered = false;
});
});
this.element
.querySelectorAll(".sortable__hole")
.forEach((dropElement: HTMLDivElement) =>
this.setupHoleListeners(dropElement)
);
}
}

File Metadata

Mime Type
text/x-java
Expires
Fri, Nov 28, 15:41 (12 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1080449
Default Alt Text
sortable.stimulus.ts (4 KB)

Event Timeline