109 lines
3.5 KiB
JavaScript
109 lines
3.5 KiB
JavaScript
/* The Mia! Accounting Flask Project
|
|
* drag-and-drop-reorder.js: The JavaScript for the reorder a list with drag-and-drop
|
|
*/
|
|
|
|
/* Copyright (c) 2023 imacat.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/* Author: imacat@mail.imacat.idv.tw (imacat)
|
|
* First written: 2023/2/3
|
|
*/
|
|
|
|
/**
|
|
* Initializes the drag-and-drop reordering on a list.
|
|
*
|
|
* @param list {HTMLElement} the list to be reordered
|
|
* @param onReorder {(function())|*} The callback to reorder the items
|
|
*/
|
|
function initializeDragAndDropReordering(list, onReorder) {
|
|
initializeMouseDragAndDropReordering(list, onReorder);
|
|
initializeTouchDragAndDropReordering(list, onReorder);
|
|
}
|
|
|
|
/**
|
|
* Initializes the drag-and-drop reordering with mouse.
|
|
*
|
|
* @param list {HTMLElement} the list to be reordered
|
|
* @param onReorder {(function())|*} The callback to reorder the items
|
|
* @private
|
|
*/
|
|
function initializeMouseDragAndDropReordering(list, onReorder) {
|
|
const items = Array.from(list.children);
|
|
let dragged = null;
|
|
items.forEach(function (item) {
|
|
item.draggable = true;
|
|
item.addEventListener("dragstart", function () {
|
|
dragged = item;
|
|
dragged.classList.add("accounting-dragged");
|
|
});
|
|
item.addEventListener("dragover", function () {
|
|
onDragOver(dragged, item);
|
|
onReorder();
|
|
});
|
|
item.addEventListener("dragend", function () {
|
|
dragged.classList.remove("accounting-dragged");
|
|
dragged = null;
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initializes the drag-and-drop reordering with touch devices.
|
|
*
|
|
* @param list {HTMLElement} the list to be reordered
|
|
* @param onReorder {(function())|*} The callback to reorder the items
|
|
* @private
|
|
*/
|
|
function initializeTouchDragAndDropReordering(list, onReorder) {
|
|
const items = Array.from(list.children);
|
|
items.forEach(function (item) {
|
|
item.addEventListener("touchstart", function () {
|
|
item.classList.add("accounting-dragged");
|
|
});
|
|
item.addEventListener("touchmove", function (event) {
|
|
const touch = event.targetTouches[0];
|
|
const target = document.elementFromPoint(touch.pageX, touch.pageY);
|
|
onDragOver(item, target);
|
|
onReorder();
|
|
});
|
|
item.addEventListener("touchend", function () {
|
|
item.classList.remove("accounting-dragged");
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Handles when an item is dragged over the other item.
|
|
*
|
|
* @param dragged {Element} the item that was dragged
|
|
* @param target {Element} the other item that was dragged over
|
|
*/
|
|
function onDragOver(dragged, target) {
|
|
if (dragged === null || target.parentElement !== dragged.parentElement || target === dragged) {
|
|
return;
|
|
}
|
|
let isBefore = false;
|
|
for (let p = target; p !== null; p = p.previousSibling) {
|
|
if (p === dragged) {
|
|
isBefore = true;
|
|
}
|
|
}
|
|
if (isBefore) {
|
|
target.parentElement.insertBefore(dragged, target.nextSibling);
|
|
} else {
|
|
target.parentElement.insertBefore(dragged, target);
|
|
}
|
|
}
|