Commit 9a8809c7 authored by ransome1's avatar ransome1
Browse files

Replaced Drag and Drop implementation

parent 78ce8707
/* Made with love by @fitri
This is a component of my ReactJS project
https://codepen.io/fitri/full/oWovYj/ */
"use strict";
import { reorderSortingLevel } from "../render.js";
function enableDragSort(listClass) {
const sortableLists = document.getElementsByClassName(listClass);
Array.prototype.map.call(sortableLists, (list) => {enableDragList(list)});
}
function enableDragList(list) {
Array.prototype.map.call(list.children, (item) => {enableDragItem(item)});
}
function enableDragItem(item) {
item.setAttribute("draggable", true)
item.ondrag = handleDrag;
item.ondragend = handleDrop;
}
function handleDrag(item) {
const selectedItem = item.target,
list = selectedItem.parentNode,
x = event.clientX,
y = event.clientY;
selectedItem.classList.add("drag-sort-active");
let swapItem = document.elementFromPoint(x, y) === null ? selectedItem : document.elementFromPoint(x, y);
if (list === swapItem.parentNode) {
swapItem = swapItem !== selectedItem.nextSibling ? swapItem : swapItem.nextSibling;
list.insertBefore(selectedItem, swapItem);
}
}
function handleDrop(item) {
item.target.classList.remove("drag-sort-active");
reorderSortingLevel();
}
//(()=> {enableDragSort("drag-sort-enable")})();
export { enableDragSort };
/* eslint-env browser */
/* jslint-env browser */
/* global window */
/* global document */
/* global console */
/*
* DragonflyJS - v1.2.0 - 2018-07-17
* https://getbutterfly.com/dragonflyjs-vanilla-javascript-drag-and-drop/
* Copyright (c) 2018 Ciprian Popescu
* Licensed GPLv3
*
* iMouseDown represents the current mouse button state: up or down
* lMouseState represents the previous mouse button state so that we can check for button clicks and button releases:
*
* if (iMouseDown && !lMouseState) {} // button clicked
* if (!iMouseDown && lMouseState) {} // button released
*/
var iMouseDown = false;
var lMouseState = false;
var dragObject = null;
var DragDrops = [];
var curTarget = null;
var lastTarget = null;
var rootParent = null;
var rootSibling = null;
Number.prototype.NaN0 = function () {
"use strict";
return isNaN(this) ? 0 : this;
};
function createDragContainer(element) {
"use strict";
var j = 0,
cDrag = DragDrops.length;
DragDrops[cDrag] = [];
element.setAttribute("DropObj", cDrag);
DragDrops[cDrag].push(element);
for (j = 0; j < element.childNodes.length; j += 1) {
if (element.childNodes[j].nodeName !== "#text") {
element.childNodes[j].setAttribute("DragObj", cDrag);
}
}
}
function getPosition(e) {
"use strict";
var left = 0,
top = 0;
while (e.offsetParent) {
left += e.offsetLeft + (e.currentStyle ? (parseInt(e.currentStyle.borderLeftWidth, 10)).NaN0() : 0);
top += e.offsetTop + (e.currentStyle ? (parseInt(e.currentStyle.borderTopWidth, 10)).NaN0() : 0);
e = e.offsetParent;
}
left += e.offsetLeft + (e.currentStyle ? (parseInt(e.currentStyle.borderLeftWidth, 10)).NaN0() : 0);
top += e.offsetTop + (e.currentStyle ? (parseInt(e.currentStyle.borderTopWidth, 10)).NaN0() : 0);
return {
x: left,
y: top
};
}
function mouseCoords(ev) {
"use strict";
if (ev.pageX || ev.pageY) {
return {
x: ev.pageX,
y: ev.pageY
};
}
return {
x: ev.clientX + document.body.scrollLeft - document.body.clientLeft,
y: ev.clientY + document.body.scrollTop - document.body.clientTop
};
}
function mouseMove(ev) {
"use strict";
ev = ev || window.event;
/*
* We are setting target to whatever item the mouse is currently on
* Firefox uses event.target here, MSIE uses event.srcElement
*/
var elementInstance,
dragHelper = document.querySelector(".drag-helper"),
activeCont = null,
target = ev.target || ev.srcElement,
mousePos = mouseCoords(ev),
origClass,
dragConts,
dragObj,
pos,
i,
j;
// mouseOut event - fires if the item the mouse is on has changed
if (lastTarget && (target !== lastTarget)) {
// Reset the classname for the target element
origClass = lastTarget.getAttribute("origClass");
if (origClass) {
lastTarget.className = origClass;
}
}
/*
* dragObj is the grouping the item is in (set from the createDragContainer function)
* if the item is not in a grouping we ignore it since it can"t be dragged with this script
*/
dragObj = target.getAttribute("DragObj");
// If the mouse was moved over an element that is draggable
if (dragObj !== null) {
// If the user is just starting to drag the element
if (iMouseDown && !lMouseState) {
// mouseDown target
curTarget = target;
// Record the mouse x and y offset for the element
rootParent = curTarget.parentNode;
rootSibling = curTarget.nextSibling;
// Remove anything that is in the dragHelper div so we can put a new item in it
for (i = 0; i < dragHelper.childNodes.length; i += 1) {
dragHelper.removeChild(dragHelper.childNodes[i]);
}
// Make a copy of the current item and put it in the drag helper
dragHelper.appendChild(curTarget.cloneNode(true));
dragHelper.style.display = "block";
// Set the class on the helper div if necessary
dragHelper.classList.add("drag-box-dragging");
// Disable dragging from the helper div (it"s already being dragged)
dragHelper.firstChild.removeAttribute("DragObj");
// Record the current position of all drag/drop targets related to the element
dragConts = DragDrops[dragObj];
// First record the width/height of the drag item, then hide it since it is going to (potentially) be moved out of its parent
curTarget.setAttribute("startWidth", parseInt(curTarget.offsetWidth, 10));
curTarget.setAttribute("startHeight", parseInt(curTarget.offsetHeight, 10));
curTarget.style.display = "none";
// Loop through each possible drop container
for (i = 0; i < dragConts.length; i += 1) {
elementInstance = dragConts[i];
pos = getPosition(dragConts[i]);
// Save the width, height and position of each container
elementInstance.setAttribute("startWidth", parseInt(elementInstance.offsetWidth, 10));
elementInstance.setAttribute("startHeight", parseInt(elementInstance.offsetHeight, 10));
elementInstance.setAttribute("startLeft", pos.x);
elementInstance.setAttribute("startTop", pos.y);
// Loop through each child element of each container
for (j = 0; j < dragConts[i].childNodes.length; j += 1) {
elementInstance = dragConts[i].childNodes[j];
if ((elementInstance.nodeName === "#text") || (dragConts[i].childNodes[j] === curTarget)) {
continue;
}
pos = getPosition(dragConts[i].childNodes[j]);
// Save the width, height and position of each element
elementInstance.setAttribute("startWidth", parseInt(elementInstance.offsetWidth, 10));
elementInstance.setAttribute("startHeight", parseInt(elementInstance.offsetHeight, 10));
elementInstance.setAttribute("startLeft", pos.x);
elementInstance.setAttribute("startTop", pos.y);
}
}
}
}
// If we get in here we are dragging something
if (curTarget) {
dragConts = DragDrops[curTarget.getAttribute("DragObj")];
var xPos = mousePos.x + (parseInt(curTarget.getAttribute("startWidth"), 10) / 2),
yPos = mousePos.y + (parseInt(curTarget.getAttribute("startHeight"), 10) / 2);
// Move helper div to wherever the mouse is
dragHelper.style.top = mousePos.y - parseInt(curTarget.getAttribute("startHeight"))/2 + "px";
dragHelper.style.left = mousePos.x - parseInt(curTarget.getAttribute("startWidth"))/2 + "px";
// Check each drop container to see if target object is "inside" the container
for (i = 0; i < dragConts.length; i += 1) {
activeCont = dragConts[i];
}
// beforeNode will hold the first node AFTER where div belongs
var beforeNode = null;
// Loop through each child node (skipping text nodes)
for (i = activeCont.childNodes.length - 1; i >= 0; i -= 1) {
elementInstance = activeCont.childNodes[i];
if (elementInstance.nodeName === "#text") {
continue;
}
// If the current item is "After" the item being dragged
if (curTarget !== activeCont.childNodes[i] && ((parseInt(elementInstance.getAttribute("startLeft"), 10) + parseInt(elementInstance.getAttribute("startWidth"), 10)) > xPos) && ((parseInt(elementInstance.getAttribute("startTop"), 10) + parseInt(elementInstance.getAttribute("startHeight"), 10)) > yPos)) {
beforeNode = activeCont.childNodes[i];
}
}
// The item being dragged belongs before another item
if (beforeNode) {
if (beforeNode !== curTarget.nextSibling) {
activeCont.insertBefore(curTarget, beforeNode);
}
// The item being dragged belongs at the end of the current container
} else {
if ((curTarget.nextSibling) || (curTarget.parentNode !== activeCont)) {
activeCont.appendChild(curTarget);
}
}
// Make drag item visible
if (curTarget.style.display !== "") {
curTarget.style.display = "";
curTarget.style.visibility = "hidden";
}
}
// Track the current mouse state so we can compare against it next time
lMouseState = iMouseDown;
// mouseMove target
lastTarget = target;
if (dragObject) {
dragObject.style.position = "absolute";
dragObject.style.top = mousePos.y;
dragObject.style.left = mousePos.x;
}
// Track the current mouse state so we can compare against it next time
lMouseState = iMouseDown;
// Prevent items on the page from being highlighted while dragging
if (curTarget || dragObject) {
return false;
}
}
function mouseUp(callback, event) {
"use strict";
if(!iMouseDown) return false;
var dragHelper = document.querySelector(".drag-helper");
if (curTarget) {
dragHelper.style.display = "none";
if (curTarget.style.display === "none") {
if (rootSibling) {
rootParent.insertBefore(curTarget, rootSibling);
} else {
rootParent.appendChild(curTarget);
}
}
curTarget.style.display = "";
curTarget.style.visibility = "visible";
}
curTarget = null;
dragObject = null;
iMouseDown = false;
// Add AJAX event here
if (typeof callback === "function") {
callback();
}
}
function mouseDown(ev) {
"use strict";
ev = ev || window.event;
var target = ev.target || ev.srcElement;
iMouseDown = true;
if (target.onmousedown || target.getAttribute("DragObj")) {
return false;
}
}
export function dragonfly(element, callback) {
"use strict";
createDragContainer(document.querySelector(element));
var dragHelper = document.createElement("div");
dragHelper.style.cssText = "position: absolute; display: none;";
dragHelper.classList.add("drag-helper");
document.body.appendChild(dragHelper);
document.getElementById("sortByContainer").addEventListener("mousemove", function () {
mouseMove();
});
document.getElementById("sortByContainer").addEventListener("mousedown", function () {
mouseDown();
});
document.addEventListener("mouseup", function (event) {
mouseUp(callback);
});
}
......@@ -382,15 +382,11 @@ body.dark .modal.content .tabs li.is-active a {
color: white;
border-color: #CCCDCF;
}
body.dark .drag-box,
body.dark .drag-box.tag,
body.dark .drag-box:hover {
body.dark #sortByContainer li {
border-bottom: 1px solid #2d2d2d;
color: white;
}
body.dark .drag-box i,
body.dark .drag-box.tag i,
body.dark .drag-box:hover i {
body.dark #sortByContainer li i {
color: #CCCDCF;
}
body.dark .message.fixed {
......@@ -1236,35 +1232,25 @@ nav ul:nth-child(2) {
#sortByContainer {
width: auto;
cursor: grab;
list-style: none;
}
#sortByContainer li:last-child {
border: none;
}
.drag-box,
.drag-box.tag,
.drag-box:hover {
#sortByContainer li {
width: 100%;
height: auto !important;
line-height: 1.5em !important;
margin: 0;
padding: 0.75em 0.5em;
cursor: grab;
text-align: left;
margin: 0 0 0.25em 0;
padding: 0.4em 1em 0.5em 1em;
white-space: nowrap;
border-bottom: 1px solid #ccc;
text-align: left;
}
.drag-box i,
.drag-box.tag i,
.drag-box:hover i {
#sortByContainer li i {
margin-right: 1em;
color: #3273dc;
}
.drag-box-dragging,
.drag-helper {
list-style: none;
cursor: grab;
border: none !important;
#sortByContainer li:last-child {
border: none;
}
.contentContainer {
......
This diff is collapsed.
......@@ -50,7 +50,7 @@
<tr>
<td id="sortBy"></td>
<td>
<ol id="sortByContainer" class="drag-container"></ol>
<ul id="sortByContainer" class="drag-sort-enable"></ul>
</td>
</tr>
<tr>
......
"use strict";
import { userData, setUserData, handleError, startBuilding, translations, resetModal } from "../render.js";
import { _paq } from "./matomo.mjs";
import { dragonfly } from "../configs/dragonfly.mjs";
//import { dragonfly } from "../configs/dragonfly.mjs";
const html = document.getElementById("html");
const body = document.getElementById("body");
......@@ -52,28 +52,23 @@ zoomRangePicker.innerHTML = translations.zoomRangePicker;
viewToggleZoom.innerHTML = translations.viewToggleZoom;
viewToggleShowEmptyFilters.innerHTML = translations.viewToggleShowEmptyFilters;
// build the sort by list
for(let i=0; i < userData.sortByLevel.length; i++) {
let sortBy = userData.sortByLevel[i];
const sortByContainerElement = document.createElement("li");
sortByContainerElement.setAttribute("class", "drag-box");
//sortByContainerElement.setAttribute("class", "drag-box");
sortByContainerElement.setAttribute("data-id", sortBy);
if(sortBy==="dueString") sortBy = "dueDate";
sortByContainerElement.innerHTML = "<i class=\"fas fa-grip-lines\" dragobj=\"0\"></i>" + translations[sortBy];
sortByContainerElement.innerHTML = "<i class=\"fas fa-grip-lines\" dragobj=\"0\"></i>";
sortByContainerElement.innerHTML += translations[sortBy];
sortByContainer.appendChild(sortByContainerElement);
if(i === userData.sortByLevel.length) resolve();
}
dragonfly("#sortByContainer", function () {
let sortByLevel = new Array;
const children = sortByContainer.children;
for(let i=0; i<children.length; i++) {
if(!children[i].getAttribute("data-id")) continue;
sortByLevel.push(children[i].getAttribute("data-id"));
}
setUserData("sortByLevel", sortByLevel);
startBuilding();
});
import { enableDragSort } from "../configs/dragndrop.mjs";
enableDragSort("drag-sort-enable");
zoomRangePicker.onchange = function() {
const value = this.value;
......
......@@ -110,6 +110,16 @@ async function getConfirmation() {
modalPrompt.classList.remove("is-active");
});
}
function reorderSortingLevel() {
let sortByLevel = new Array;
const children = sortByContainer.children;
for(let i=0; i<children.length; i++) {
if(!children[i].getAttribute("data-id")) continue;
sortByLevel.push(children[i].getAttribute("data-id"));
}
setUserData("sortByLevel", sortByLevel);
startBuilding();
}
function configureMainView() {
try {
// close filterContext if open
......@@ -619,18 +629,6 @@ function resetModal(modal) {
return Promise.reject(error);
}
}
// function setButtonState(button) {
// switch (button) {
// case "btnArchiveTodos":
// if(todos.items.complete.length>0) {
// btnArchiveTodos.disabled = false;
// } else {
// btnArchiveTodos.disabled = true;
// }
// break;
// default:
// }
// }
function setTheme(switchTheme) {
try {
let theme = userData.theme;
......@@ -931,4 +929,4 @@ window.api.receive("refresh", async function(content) {
});
});
export { resetModal, setUserData, startBuilding, handleError, userData, appData, translations, modal, setTheme, getConfirmation };
export { resetModal, setUserData, startBuilding, handleError, userData, appData, translations, modal, setTheme, getConfirmation, reorderSortingLevel };
......@@ -428,13 +428,13 @@ body.dark {
border-color: $lighter-grey;
}
}
.drag-box,
.drag-box.tag,
.drag-box:hover {
border-bottom: 1px solid $darker-grey;
color: white;
i {
color: $lighter-grey;
#sortByContainer {
li {
border-bottom: 1px solid $darker-grey;
color: white;
i {
color: $lighter-grey;
}
}
}
.message.fixed {
......
......@@ -744,32 +744,46 @@ nav {
#sortByContainer {
width: auto;
cursor: grab;
list-style: none;
li {
width: 100%;
height: auto!important;
line-height: 1.5em!important;
margin: 0;
padding: 0.75em 0.5em;
cursor: grab;
white-space: nowrap;
border-bottom: 1px solid $mid-grey;
text-align: left;
i {
margin-right: 1em;
color: $has-text-link;
}
}
li:last-child {
border: none;
}
}
.drag-box,
.drag-box.tag,
.drag-box:hover {
cursor: grab;
text-align: left;
margin: 0 0 0.25em 0;
padding: 0.4em 1em 0.5em 1em;
white-space: nowrap;
border-bottom: 1px solid $mid-grey;
i {
margin-right: 1em;
color: $has-text-link;
}
}
.drag-box-dragging,
.drag-helper {
list-style: none;
cursor: grab;
border: none!important;
}
// .drag-box,
// .drag-box.tag,
// .drag-box:hover {