nested-sort
Advanced tools
Comparing version 5.0.0 to 5.0.1
@@ -1,2 +0,2 @@ | ||
import { DataEngineOptions, DataItem, ListElement, PropertyMap } from './types'; | ||
import { DataEngineOptions, DataItem, ListElement, MappedDataItem, PropertyMap } from './types'; | ||
declare class DataEngine { | ||
@@ -19,8 +19,8 @@ data: Array<DataItem>; | ||
elementIsAncestorOfItem(node: HTMLElement, item: DataItem): boolean; | ||
getDirectListParentOfItem(node: HTMLElement, item: DataItem): HTMLElement; | ||
getDirectListParentOfItem(node: HTMLElement, item: DataItem): HTMLElement | null; | ||
maybeAppendItemToParentDom(item: DataItem): boolean; | ||
getListItemsDom(): Array<HTMLElement>; | ||
convertDomToData(list: ListElement): Array<Record<string, unknown>>; | ||
render(): ListElement; | ||
convertDomToData(list: ListElement): Array<MappedDataItem>; | ||
render(): Node; | ||
} | ||
export default DataEngine; |
import DataEngine from './data-engine'; | ||
import { Actions, ClassNames, ClassNamesList, Cursor, DataItem, Dimensions, Distances, DropLocation, EventListeners, ListElement, ListInterface, ListTagName, Options, PlaceholderMaintenanceActions, PropertyMap, TargetNode } from './types'; | ||
import { Actions, ClassNames, ClassNamesList, Cursor, DataItem, Distances, DropLocation, EventListeners, ListElement, ListInterface, ListTagName, Options, PlaceholderMaintenanceActions, PropertyMap, TargetNode } from './types'; | ||
declare class NestedSort { | ||
actions: Actions; | ||
classNames: ClassNames; | ||
cursor: Cursor; | ||
data: Array<DataItem>; | ||
dataEngine: DataEngine; | ||
draggedNode: HTMLElement; | ||
distances: Partial<Distances>; | ||
draggedNode?: HTMLElement; | ||
initialised: boolean; | ||
listClassNames: Array<string>; | ||
listEventListeners: EventListeners; | ||
listInterface: ListInterface; | ||
listItemClassNames: Array<string>; | ||
mainListClassName: string; | ||
nestingLevels: number; | ||
placeholderList: HTMLElement; | ||
placeholderInUse: HTMLElement; | ||
propertyMap: Partial<PropertyMap>; | ||
el: HTMLElement; | ||
selector: string; | ||
sortableList: ListElement; | ||
targetedNode: HTMLElement; | ||
targetedNode?: HTMLElement; | ||
targetNode: TargetNode; | ||
distances: Distances; | ||
dimensions: Dimensions; | ||
cursor: Cursor; | ||
classNames: ClassNames; | ||
listEventListeners: EventListeners; | ||
nestingLevels: number; | ||
listInterface: ListInterface; | ||
wrapper?: Element; | ||
constructor({ actions, data, droppingEdge, el, init, listClassNames, listItemClassNames, nestingLevels, propertyMap, }: Options); | ||
@@ -41,3 +39,3 @@ getListInterface(): ListInterface; | ||
destroy(): void; | ||
removeClassFromEl(el: HTMLElement, className: string): void; | ||
removeClassFromEl(className: string, el?: HTMLElement): void; | ||
canBeTargeted(el: HTMLElement): boolean; | ||
@@ -50,3 +48,3 @@ onDragStart(e: DragEvent): void; | ||
updateCoordination(e: DragEvent): void; | ||
getDropLocation(): DropLocation; | ||
getDropLocation(): DropLocation | undefined; | ||
maybeDrop(): void; | ||
@@ -56,3 +54,3 @@ dropTheItem(place: DropLocation): void; | ||
calcMouseToTargetedElDist(): void; | ||
areNested(child: HTMLElement, parent: HTMLElement): boolean; | ||
areNested(child: HTMLElement | undefined, parent: HTMLElement | undefined): boolean; | ||
cursorIsIndentedEnough(): boolean; | ||
@@ -59,0 +57,0 @@ mouseIsTooCloseToTop(): boolean; |
'use strict'; | ||
class DataEngine { | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
} | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
} | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _toConsumableArray(arr) { | ||
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); | ||
} | ||
function _arrayWithoutHoles(arr) { | ||
if (Array.isArray(arr)) return _arrayLikeToArray(arr); | ||
} | ||
function _iterableToArray(iter) { | ||
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); | ||
} | ||
function _unsupportedIterableToArray(o, minLen) { | ||
if (!o) return; | ||
if (typeof o === "string") return _arrayLikeToArray(o, minLen); | ||
var n = Object.prototype.toString.call(o).slice(8, -1); | ||
if (n === "Object" && o.constructor) n = o.constructor.name; | ||
if (n === "Map" || n === "Set") return Array.from(o); | ||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); | ||
} | ||
function _arrayLikeToArray(arr, len) { | ||
if (len == null || len > arr.length) len = arr.length; | ||
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; | ||
return arr2; | ||
} | ||
function _nonIterableSpread() { | ||
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); | ||
} | ||
var DataEngine = /*#__PURE__*/function () { | ||
/** | ||
* @constructor | ||
* @param {object[]} [data] | ||
* @param {object} [propertyMap={}] | ||
*/ | ||
constructor({ data, propertyMap = {} }) { | ||
function DataEngine(_ref) { | ||
var data = _ref.data, | ||
_ref$propertyMap = _ref.propertyMap, | ||
propertyMap = _ref$propertyMap === void 0 ? {} : _ref$propertyMap; | ||
_classCallCheck(this, DataEngine); | ||
_defineProperty(this, "data", void 0); | ||
_defineProperty(this, "sortedData", void 0); | ||
_defineProperty(this, "sortedDataDomArray", void 0); | ||
_defineProperty(this, "propertyMap", void 0); | ||
this.data = data; | ||
@@ -14,48 +96,47 @@ this.sortedData = []; | ||
this.propertyMap = propertyMap; | ||
this.maybeTransformData(); | ||
} | ||
maybeTransformData() { | ||
if (!Object.keys(this.propertyMap).length || !Array.isArray(this.data)) return | ||
_createClass(DataEngine, [{ | ||
key: "maybeTransformData", | ||
value: function maybeTransformData() { | ||
if (!Object.keys(this.propertyMap).length || !Array.isArray(this.data)) return; | ||
var getItemPropProxyName = this.getItemPropProxyName.bind(this); | ||
this.data = this.data.map(function (item) { | ||
return new Proxy(item, { | ||
get: function get(target, prop, receiver) { | ||
return Reflect.get(target, getItemPropProxyName(prop), receiver); | ||
} | ||
}); | ||
}); | ||
} | ||
}, { | ||
key: "getItemPropProxyName", | ||
value: function getItemPropProxyName(prop) { | ||
if (Object.prototype.hasOwnProperty.call(this.propertyMap, prop)) { | ||
return this.propertyMap[prop]; | ||
} | ||
const getItemPropProxyName = this.getItemPropProxyName.bind(this); | ||
this.data = this.data.map(item => { | ||
return new Proxy(item, { | ||
get(target, prop, receiver) { | ||
return Reflect.get(target, getItemPropProxyName(prop), receiver) | ||
}, | ||
}) | ||
}); | ||
} | ||
/** | ||
* @param {PropertyKey} prop | ||
* @returns {PropertyKey} | ||
*/ | ||
getItemPropProxyName(prop) { | ||
if (Object.prototype.hasOwnProperty.call(this.propertyMap, prop)) { | ||
return this.propertyMap[prop] | ||
return prop; | ||
} | ||
return prop | ||
} | ||
}, { | ||
key: "isTopLevelItem", | ||
value: function isTopLevelItem(item) { | ||
return !item.parent; | ||
} | ||
}, { | ||
key: "sortListItems", | ||
value: function sortListItems() { | ||
var _this = this; | ||
isTopLevelItem(item) { | ||
return !item.parent | ||
} | ||
var items = _toConsumableArray(this.data); | ||
/** | ||
* @returns {object[]} | ||
*/ | ||
sortListItems() { | ||
const items = [...this.data]; | ||
const topLevelItems = items | ||
.filter(a => this.isTopLevelItem(a)) | ||
.sort((a, b) => a.order && b.order ? a.order - b.order : 0); | ||
const childItems = items | ||
.filter(a => !this.isTopLevelItem(a)) | ||
.reduce((groups, item) => { | ||
var topLevelItems = items.filter(function (a) { | ||
return _this.isTopLevelItem(a); | ||
}).sort(function (a, b) { | ||
return a.order && b.order ? a.order - b.order : 0; | ||
}); | ||
var childItems = items.filter(function (a) { | ||
return !_this.isTopLevelItem(a); | ||
}).reduce(function (groups, item) { | ||
if (Object.prototype.hasOwnProperty.call(groups, item.parent)) { | ||
@@ -66,184 +147,195 @@ groups[item.parent].push(item); | ||
} | ||
return groups | ||
return groups; | ||
}, {}); | ||
Object.keys(childItems).forEach(function (parentId) { | ||
childItems[parentId].sort(function (a, b) { | ||
return a.order && b.order ? a.order - b.order : 0; | ||
}); | ||
}); | ||
this.sortedData = [].concat(_toConsumableArray(topLevelItems), _toConsumableArray(Object.values(childItems).flat())); | ||
return this.sortedData; | ||
} | ||
}, { | ||
key: "createItemElement", | ||
value: function createItemElement(item) { | ||
var nodeName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'li'; | ||
var id = item.id, | ||
text = item.text; | ||
var el = document.createElement(nodeName); | ||
el.dataset.id = id; | ||
if (nodeName === 'li' && text) el.innerHTML = text; | ||
return el; | ||
} | ||
}, { | ||
key: "elementIsParentOfItem", | ||
value: function elementIsParentOfItem(node, item) { | ||
return node.dataset.id === "".concat(item.parent); | ||
} | ||
}, { | ||
key: "getParentNodeOfItem", | ||
value: function getParentNodeOfItem(node, item, nodeName) { | ||
return node.querySelector("".concat(nodeName, "[data-id=\"").concat(item.parent, "\"]")); | ||
} | ||
}, { | ||
key: "elementIsAncestorOfItem", | ||
value: function elementIsAncestorOfItem(node, item) { | ||
return !!this.getParentNodeOfItem(node, item, 'li'); | ||
} | ||
}, { | ||
key: "getDirectListParentOfItem", | ||
value: function getDirectListParentOfItem(node, item) { | ||
return this.getParentNodeOfItem(node, item, 'ol'); | ||
} | ||
}, { | ||
key: "maybeAppendItemToParentDom", | ||
value: function maybeAppendItemToParentDom(item) { | ||
var _this2 = this; | ||
Object.keys(childItems).forEach(parentId => { | ||
childItems[parentId].sort((a, b) => a.order && b.order ? a.order - b.order : 0); | ||
}); | ||
var parent = item.parent; | ||
var topParent = this.sortedDataDomArray.find(function (topLevelListItem) { | ||
return _this2.elementIsParentOfItem(topLevelListItem, item) || _this2.elementIsAncestorOfItem(topLevelListItem, item); | ||
}); | ||
if (!topParent) return false; | ||
var listItem = this.createItemElement(item); | ||
var directParentList = this.getDirectListParentOfItem(topParent, item); | ||
this.sortedData = [ | ||
...topLevelItems, | ||
...Object.values(childItems).flat(), | ||
]; | ||
if (!directParentList) { | ||
// we need to create the direct parent OL and append it to the direct parent LI | ||
directParentList = this.createItemElement({ | ||
id: parent | ||
}, 'ol'); | ||
var directParentListItem = this.getParentNodeOfItem(topParent, item, 'li') || topParent; | ||
directParentListItem.appendChild(directParentList); | ||
} | ||
return this.sortedData | ||
} | ||
directParentList.appendChild(listItem); | ||
return true; | ||
} | ||
}, { | ||
key: "getListItemsDom", | ||
value: function getListItemsDom() { | ||
var _this3 = this; | ||
/** | ||
* @param {object[]} item | ||
* @param {string} nodeName | ||
* @returns {HTMLElement} | ||
*/ | ||
createItemElement(item, nodeName = 'li') { | ||
const { id, text } = item; | ||
const el = document.createElement(nodeName); | ||
el.dataset.id = id; | ||
if (nodeName === 'li') el.innerHTML = text; | ||
this.sortedDataDomArray = []; | ||
var processedItems = []; | ||
return el | ||
} | ||
while (processedItems.length !== this.sortListItems().length) { | ||
processedItems = this.sortedData.reduce(function (processedItems, item) { | ||
var id = item.id.toString(); | ||
if (processedItems.includes(id)) return processedItems; | ||
var itemAdded; | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
elementIsParentOfItem(node, item) { | ||
return node.dataset.id === `${item.parent}` | ||
} | ||
if (!item.parent) { | ||
var listItem = _this3.createItemElement(item); | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @param {string} nodeName | ||
* @returns {Element|null} | ||
*/ | ||
getParentNodeOfItem(node, item, nodeName) { | ||
return node.querySelector(`${nodeName}[data-id="${item.parent}"]`) | ||
} | ||
_this3.sortedDataDomArray.push(listItem); | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
elementIsAncestorOfItem(node, item) { | ||
return !!this.getParentNodeOfItem(node, item, 'li') | ||
} | ||
itemAdded = true; | ||
} else { | ||
itemAdded = _this3.maybeAppendItemToParentDom(item); | ||
} | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {HTMLElement} | ||
*/ | ||
getDirectListParentOfItem(node, item) { | ||
return this.getParentNodeOfItem(node, item, 'ol') | ||
} | ||
if (itemAdded) processedItems.push(id); | ||
return processedItems; | ||
}, processedItems); | ||
} | ||
/** | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
maybeAppendItemToParentDom(item) { | ||
const { parent } = item; | ||
const topParent = this.sortedDataDomArray.find(topLevelListItem => { | ||
return this.elementIsParentOfItem(topLevelListItem, item) || this.elementIsAncestorOfItem(topLevelListItem, item) | ||
}); | ||
return this.sortedDataDomArray; | ||
} | ||
}, { | ||
key: "convertDomToData", | ||
value: function convertDomToData(list) { | ||
var _this4 = this; | ||
if (!topParent) return false | ||
return Array.from((list === null || list === void 0 ? void 0 : list.querySelectorAll('li')) || []).map(function (li) { | ||
var _ref2; | ||
const listItem = this.createItemElement(item); | ||
let directParentList = this.getDirectListParentOfItem(topParent, item); | ||
if (!directParentList) { | ||
// we need to create the direct parent OL and append it to the direct parent LI | ||
directParentList = this.createItemElement({ id: parent }, 'ol'); | ||
const directParentListItem = this.getParentNodeOfItem(topParent, item, 'li') || topParent; | ||
directParentListItem.appendChild(directParentList); | ||
var parentListItem = li.parentNode; | ||
var parent = parentListItem.dataset.id; | ||
var order = Array.from(parentListItem.children).findIndex(function (item) { | ||
return item === li; | ||
}) + 1; | ||
return _ref2 = {}, _defineProperty(_ref2, _this4.getItemPropProxyName('id'), li.dataset.id), _defineProperty(_ref2, _this4.getItemPropProxyName('parent'), parent), _defineProperty(_ref2, _this4.getItemPropProxyName('order'), order), _ref2; | ||
}); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var list = document.createElement('ol'); | ||
this.getListItemsDom().forEach(function (listItem) { | ||
return list.appendChild(listItem); | ||
}); | ||
return list; | ||
} | ||
}]); | ||
directParentList.appendChild(listItem); | ||
return DataEngine; | ||
}(); | ||
return true | ||
} | ||
var NestedSort = /*#__PURE__*/function () { | ||
function NestedSort(_ref) { | ||
var _ref$actions = _ref.actions, | ||
actions = _ref$actions === void 0 ? {} : _ref$actions, | ||
data = _ref.data, | ||
_ref$droppingEdge = _ref.droppingEdge, | ||
droppingEdge = _ref$droppingEdge === void 0 ? 15 : _ref$droppingEdge, | ||
el = _ref.el, | ||
_ref$init = _ref.init, | ||
init = _ref$init === void 0 ? true : _ref$init, | ||
listClassNames = _ref.listClassNames, | ||
listItemClassNames = _ref.listItemClassNames, | ||
nestingLevels = _ref.nestingLevels, | ||
_ref$propertyMap = _ref.propertyMap, | ||
propertyMap = _ref$propertyMap === void 0 ? {} : _ref$propertyMap; | ||
/** | ||
* @returns {array} | ||
*/ | ||
getListItemsDom() { | ||
this.sortedDataDomArray = []; | ||
let processedItems = []; | ||
_classCallCheck(this, NestedSort); | ||
while (processedItems.length !== this.sortListItems().length) { | ||
processedItems = this.sortedData.reduce((processedItems, item) => { | ||
const { id } = item; | ||
if (processedItems.includes(id)) return processedItems | ||
_defineProperty(this, "actions", void 0); | ||
let itemAdded; | ||
if (!item.parent) { | ||
const listItem = this.createItemElement(item); | ||
this.sortedDataDomArray.push(listItem); | ||
itemAdded = true; | ||
} else { | ||
itemAdded = this.maybeAppendItemToParentDom(item); | ||
} | ||
_defineProperty(this, "classNames", void 0); | ||
if (itemAdded) processedItems.push(id); | ||
_defineProperty(this, "cursor", void 0); | ||
return processedItems | ||
}, processedItems); | ||
} | ||
_defineProperty(this, "data", void 0); | ||
return this.sortedDataDomArray | ||
} | ||
_defineProperty(this, "dataEngine", void 0); | ||
/** | ||
* @param {HTMLOListElement|HTMLUListElement} list | ||
* @returns {object[]} | ||
*/ | ||
convertDomToData(list) { | ||
return Array.from(list.querySelectorAll('li')).map(li => { | ||
const parentListItem = li.parentNode; | ||
const parent = parentListItem.dataset.id; | ||
const order = Array.from(parentListItem.children).findIndex(item => item === li) + 1; | ||
_defineProperty(this, "distances", void 0); | ||
return { | ||
[this.getItemPropProxyName('id')]: li.dataset.id, | ||
[this.getItemPropProxyName('parent')]: parent, | ||
[this.getItemPropProxyName('order')]: order, | ||
} | ||
}) | ||
} | ||
_defineProperty(this, "draggedNode", void 0); | ||
/** | ||
* @returns {HTMLOListElement} | ||
*/ | ||
render() { | ||
const list = document.createElement('ol'); | ||
this.getListItemsDom().forEach(listItem => list.appendChild(listItem)); | ||
return list | ||
} | ||
} | ||
_defineProperty(this, "initialised", void 0); | ||
class NestedSort { | ||
/** | ||
* @constructor | ||
* @param {object} [actions={}] | ||
* @param {array} [data] | ||
* @param {number} [droppingEdge=15] | ||
* @param {string|HTMLElement} el | ||
* @param {boolean} [init=true] | ||
* @param {array|string} [listClassNames] | ||
* @param {array|string} [listItemClassNames] | ||
* @param {number|string} [nestingLevels] | ||
* @param {object} [propertyMap={}] | ||
*/ | ||
constructor({ | ||
actions: { onDrop } = {}, | ||
data, | ||
droppingEdge = 15, | ||
el, | ||
init = true, | ||
listClassNames, | ||
listItemClassNames, | ||
nestingLevels, | ||
propertyMap = {}, | ||
}) { | ||
_defineProperty(this, "listClassNames", void 0); | ||
_defineProperty(this, "listEventListeners", void 0); | ||
_defineProperty(this, "listInterface", void 0); | ||
_defineProperty(this, "listItemClassNames", void 0); | ||
_defineProperty(this, "mainListClassName", void 0); | ||
_defineProperty(this, "nestingLevels", void 0); | ||
_defineProperty(this, "placeholderList", void 0); | ||
_defineProperty(this, "placeholderInUse", void 0); | ||
_defineProperty(this, "propertyMap", void 0); | ||
_defineProperty(this, "sortableList", void 0); | ||
_defineProperty(this, "targetedNode", void 0); | ||
_defineProperty(this, "targetNode", void 0); | ||
_defineProperty(this, "wrapper", void 0); | ||
var element = typeof el === 'string' ? document.querySelector(el) : el; | ||
var elementIsAList = element instanceof HTMLOListElement || element instanceof HTMLUListElement; | ||
this.wrapper = elementIsAList ? undefined : element; | ||
this.sortableList = elementIsAList ? element : null; | ||
this.data = data; | ||
this.selector = el; | ||
this.sortableList = null; | ||
this.placeholderList = null; | ||
this.placeholderInUse = null; | ||
this.draggedNode = null; | ||
this.targetedNode = null; | ||
this.listClassNames = this.createListClassNamesArray(listClassNames); | ||
@@ -254,29 +346,12 @@ this.mainListClassName = this.listClassNames[0] || 'nested-sort'; | ||
this.actions = { | ||
onDrop, | ||
onDrop: actions.onDrop | ||
}; | ||
this.initialised = false; | ||
this.targetNode = { | ||
X: null, | ||
Y: null, | ||
}; | ||
this.distances = { | ||
droppingEdge, | ||
droppingEdgeNegative: droppingEdge * -1, | ||
mouseTo: { | ||
targetedElTop: undefined, | ||
}, | ||
droppingEdge: droppingEdge | ||
}; | ||
this.dimensions = { | ||
targetedEl: { | ||
H: undefined, | ||
}, | ||
}; | ||
this.cursor = { | ||
X: null, | ||
Y: null, | ||
}; | ||
this.classNames = { | ||
dragged: 'ns-dragged', | ||
placeholder: 'ns-placeholder', | ||
targeted: 'ns-targeted', | ||
targeted: 'ns-targeted' | ||
}; | ||
@@ -288,8 +363,8 @@ this.listEventListeners = { | ||
dragend: this.onDragEnd.bind(this), | ||
drop: this.onDrop.bind(this), | ||
drop: this.onDrop.bind(this) | ||
}; | ||
const intNestingLevels = parseInt(nestingLevels); | ||
var intNestingLevels = parseInt(nestingLevels); | ||
this.nestingLevels = isNaN(intNestingLevels) ? -1 : intNestingLevels; // values less than 0 mean infinite levels of nesting | ||
this.listInterface = this.getListInterface(); | ||
this.maybeInitDataDom(); | ||
@@ -300,344 +375,411 @@ this.addListAttributes(); | ||
getListInterface() { | ||
if (Array.isArray(this.data) && this.data.length) return HTMLOListElement | ||
_createClass(NestedSort, [{ | ||
key: "getListInterface", | ||
value: function getListInterface() { | ||
if (Array.isArray(this.data) && this.data.length) return HTMLOListElement; | ||
return this.sortableList instanceof HTMLOListElement ? HTMLOListElement : HTMLUListElement; | ||
} | ||
}, { | ||
key: "getDataEngine", | ||
value: function getDataEngine() { | ||
if (this.dataEngine) return this.dataEngine; | ||
this.dataEngine = new DataEngine({ | ||
data: this.data, | ||
propertyMap: this.propertyMap | ||
}); | ||
return this.dataEngine; | ||
} | ||
}, { | ||
key: "createListClassNamesArray", | ||
value: function createListClassNamesArray(listClassNames) { | ||
if (!listClassNames) return []; | ||
return Array.isArray(listClassNames) ? listClassNames : listClassNames.split(' '); | ||
} | ||
}, { | ||
key: "maybeInitDataDom", | ||
value: function maybeInitDataDom() { | ||
if (!(Array.isArray(this.data) && this.data.length && this.wrapper)) return; | ||
var list = this.getDataEngine().render(); | ||
this.wrapper.innerHTML = ''; | ||
this.wrapper.appendChild(list); | ||
} | ||
}, { | ||
key: "getListTagName", | ||
value: function getListTagName() { | ||
return this.listInterface === HTMLOListElement ? 'ol' : 'ul'; | ||
} | ||
}, { | ||
key: "getSortableList", | ||
value: function getSortableList() { | ||
var _this$wrapper; | ||
const el = this.selector instanceof HTMLElement | ||
? this.selector | ||
: document.querySelector(this.selector); | ||
return el instanceof HTMLOListElement ? HTMLOListElement : HTMLUListElement | ||
} | ||
getDataEngine() { | ||
if (this.dataEngine instanceof DataEngine) { | ||
return this.dataEngine | ||
if (this.sortableList instanceof this.listInterface) return this.sortableList; | ||
this.sortableList = (_this$wrapper = this.wrapper) === null || _this$wrapper === void 0 ? void 0 : _this$wrapper.querySelector(this.getListTagName()); | ||
return this.sortableList; | ||
} | ||
this.dataEngine = new DataEngine({data: this.data, propertyMap: this.propertyMap}); | ||
return this.dataEngine | ||
} | ||
}, { | ||
key: "addListAttributes", | ||
value: function addListAttributes() { | ||
var _list$classList, | ||
_this = this; | ||
createListClassNamesArray(listClassNames) { | ||
if (!listClassNames) return [] | ||
return Array.isArray(listClassNames) ? listClassNames : listClassNames.split(' ') | ||
} | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
maybeInitDataDom() { | ||
if (!(Array.isArray(this.data) && this.data.length)) return | ||
(_list$classList = list.classList).add.apply(_list$classList, _toConsumableArray(this.listClassNames.concat(this.mainListClassName))); | ||
const wrapper = document.querySelector(this.selector); | ||
const list = this.getDataEngine().render(); | ||
wrapper.innerHTML = ''; | ||
wrapper.appendChild(list); | ||
} | ||
list.querySelectorAll(this.getListTagName()).forEach(function (l) { | ||
var _l$classList; | ||
getListTagName() { | ||
return this.listInterface === HTMLOListElement ? 'ol' : 'ul' | ||
} | ||
(_l$classList = l.classList).add.apply(_l$classList, _toConsumableArray(_this.listClassNames)); | ||
}); | ||
list.querySelectorAll('li').forEach(function (li) { | ||
var _li$classList; | ||
getSortableList() { | ||
if (this.sortableList instanceof this.listInterface) return this.sortableList | ||
(_li$classList = li.classList).add.apply(_li$classList, _toConsumableArray(_this.listItemClassNames)); | ||
}); | ||
} | ||
}, { | ||
key: "toggleMainListLifeCycleClassName", | ||
value: function toggleMainListLifeCycleClassName() { | ||
var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
var className = "".concat(this.mainListClassName, "--enabled"); | ||
enabled ? list.classList.add(className) : list.classList.remove(className); | ||
} | ||
}, { | ||
key: "toggleListItemAttributes", | ||
value: function toggleListItemAttributes() { | ||
var _this$getSortableList; | ||
if (this.selector instanceof this.listInterface) { | ||
this.sortableList = this.selector; | ||
} else { | ||
const list = document.querySelector(this.selector); | ||
this.sortableList = list instanceof this.listInterface | ||
? list | ||
: list.querySelector(this.getListTagName()); | ||
var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
(_this$getSortableList = this.getSortableList()) === null || _this$getSortableList === void 0 ? void 0 : _this$getSortableList.querySelectorAll('li').forEach(function (el) { | ||
el.setAttribute('draggable', enable.toString()); | ||
}); | ||
} | ||
}, { | ||
key: "toggleListEventListeners", | ||
value: function toggleListEventListeners() { | ||
var _this2 = this; | ||
return this.sortableList | ||
} | ||
var remove = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
Object.keys(this.listEventListeners).forEach(function (event) { | ||
remove ? list.removeEventListener(event, _this2.listEventListeners[event]) : list.addEventListener(event, _this2.listEventListeners[event], false); | ||
}); | ||
} | ||
}, { | ||
key: "initDragAndDrop", | ||
value: function initDragAndDrop() { | ||
if (this.initialised) return; | ||
this.toggleListEventListeners(); | ||
this.initPlaceholderList(); | ||
this.toggleListItemAttributes(); | ||
this.toggleMainListLifeCycleClassName(); | ||
this.initialised = true; | ||
} | ||
}, { | ||
key: "init", | ||
value: function init() { | ||
this.initDragAndDrop(); | ||
} | ||
}, { | ||
key: "destroy", | ||
value: function destroy() { | ||
this.toggleListEventListeners(true); | ||
this.toggleListItemAttributes(false); | ||
this.toggleMainListLifeCycleClassName(false); | ||
this.initialised = false; | ||
} | ||
}, { | ||
key: "removeClassFromEl", | ||
value: function removeClassFromEl(className, el) { | ||
if (el && el.classList.contains(className)) { | ||
el.classList.remove(className); | ||
} | ||
} | ||
}, { | ||
key: "canBeTargeted", | ||
value: function canBeTargeted(el) { | ||
if (!this.draggedNode || this.draggedNode === el) return false; | ||
return el.nodeName === 'LI' || el instanceof this.listInterface && el.classList.contains(this.classNames.placeholder); | ||
} | ||
}, { | ||
key: "onDragStart", | ||
value: function onDragStart(e) { | ||
var _e$dataTransfer; | ||
addListAttributes() { | ||
const list = this.getSortableList(); | ||
this.draggedNode = e.target; | ||
this.draggedNode.classList.add(this.classNames.dragged); | ||
(_e$dataTransfer = e.dataTransfer) === null || _e$dataTransfer === void 0 ? void 0 : _e$dataTransfer.setData('text', 'Drag started!'); // Hack for Firefox! | ||
} | ||
}, { | ||
key: "onDragOver", | ||
value: function onDragOver(e) { | ||
e.preventDefault(); // prevent default to allow drop | ||
list.classList.add(...this.listClassNames.concat(this.mainListClassName)); | ||
list.querySelectorAll(this.getListTagName()).forEach(l => { | ||
l.classList.add(...this.listClassNames); | ||
}); | ||
this.updateCoordination(e); | ||
this.managePlaceholderLists(); | ||
} | ||
}, { | ||
key: "onDragEnter", | ||
value: function onDragEnter(e) { | ||
if (!this.canBeTargeted(e.target)) return; | ||
this.removeClassFromEl(this.classNames.targeted, this.targetedNode); | ||
this.targetedNode = e.target; | ||
this.targetedNode.classList.add(this.classNames.targeted); | ||
} | ||
}, { | ||
key: "onDragEnd", | ||
value: function onDragEnd(e) { | ||
e.stopPropagation(); | ||
this.removeClassFromEl(this.classNames.dragged, this.draggedNode); | ||
this.removeClassFromEl(this.classNames.targeted, this.targetedNode); | ||
this.cleanupPlaceholderLists(); | ||
delete this.draggedNode; | ||
delete this.targetedNode; | ||
} | ||
}, { | ||
key: "onDrop", | ||
value: function onDrop(e) { | ||
e.stopPropagation(); | ||
this.maybeDrop(); | ||
this.cleanupPlaceholderLists(); | ||
list.querySelectorAll('li').forEach(li => { | ||
li.classList.add(...this.listItemClassNames); | ||
}); | ||
} | ||
toggleMainListLifeCycleClassName(enabled = true) { | ||
const className = `${this.mainListClassName}--enabled`; | ||
const classList = this.getSortableList().classList; | ||
return enabled | ||
? classList.add(className) | ||
: classList.remove(className) | ||
} | ||
toggleListItemAttributes(enable = true) { | ||
this.getSortableList().querySelectorAll('li').forEach(el => { | ||
el.setAttribute('draggable', enable); | ||
}); | ||
} | ||
toggleListEventListeners(remove = false) { | ||
const list = this.getSortableList(); | ||
Object.keys(this.listEventListeners).forEach(event => { | ||
if (remove) { | ||
list.removeEventListener(event, this.listEventListeners[event]); | ||
} else { | ||
list.addEventListener(event, this.listEventListeners[event], false); | ||
if (typeof this.actions.onDrop === 'function') { | ||
this.actions.onDrop(this.getDataEngine().convertDomToData(this.getSortableList())); | ||
} | ||
}); | ||
} | ||
initDragAndDrop() { | ||
if (this.initialised) return | ||
this.toggleListEventListeners(); | ||
this.initPlaceholderList(); | ||
this.toggleListItemAttributes(); | ||
this.toggleMainListLifeCycleClassName(); | ||
this.initialised = true; | ||
} | ||
init() { | ||
this.initDragAndDrop(); | ||
} | ||
destroy() { | ||
this.toggleListEventListeners(true); | ||
this.toggleListItemAttributes(false); | ||
this.toggleMainListLifeCycleClassName(false); | ||
this.initialised = false; | ||
} | ||
removeClassFromEl(el, className) { | ||
if (el && el.classList.contains(className)) { | ||
el.classList.remove(className); | ||
} | ||
} | ||
}, { | ||
key: "updateCoordination", | ||
value: function updateCoordination(e) { | ||
this.calcMouseCoords(e); | ||
this.calcMouseToTargetedElDist(); | ||
} | ||
}, { | ||
key: "getDropLocation", | ||
value: function getDropLocation() { | ||
if (this.canBeDropped()) { | ||
var _this$targetedNode; | ||
canBeTargeted(el) { | ||
if (!this.draggedNode || this.draggedNode === el) return false | ||
return el.nodeName === 'LI' || (el instanceof this.listInterface && el.classList.contains(this.classNames.placeholder)) | ||
} | ||
onDragStart(e) { | ||
this.draggedNode = e.target; | ||
this.draggedNode.classList.add(this.classNames.dragged); | ||
e.dataTransfer.setData('text', 'Drag started!'); // Hack for Firefox! | ||
} | ||
onDragOver(e) { | ||
e.preventDefault(); // prevent default to allow drop | ||
this.updateCoordination(e); | ||
this.managePlaceholderLists(e); | ||
} | ||
onDragEnter(e) { | ||
if (!this.canBeTargeted(e.target)) return | ||
this.removeClassFromEl(this.targetedNode, this.classNames.targeted); | ||
this.targetedNode = e.target; | ||
this.targetedNode.classList.add(this.classNames.targeted); | ||
} | ||
onDragEnd(e) { | ||
e.stopPropagation(); | ||
this.removeClassFromEl(this.draggedNode, this.classNames.dragged); | ||
this.removeClassFromEl(this.targetedNode, this.classNames.targeted); | ||
this.cleanupPlaceholderLists(); | ||
this.draggedNode = null; | ||
this.targetedNode = null; | ||
} | ||
onDrop(e) { | ||
e.stopPropagation(); | ||
this.maybeDrop(); | ||
this.cleanupPlaceholderLists(); | ||
if (typeof this.actions.onDrop === 'function') { | ||
this.actions.onDrop(this.getDataEngine().convertDomToData(this.getSortableList())); | ||
if (((_this$targetedNode = this.targetedNode) === null || _this$targetedNode === void 0 ? void 0 : _this$targetedNode.nodeName) === 'LI') return 'before';else if (this.targetedNode instanceof this.listInterface) return 'inside'; | ||
} | ||
} | ||
} | ||
}, { | ||
key: "maybeDrop", | ||
value: function maybeDrop() { | ||
var location = this.getDropLocation(); | ||
if (location) this.dropTheItem(location); | ||
} | ||
}, { | ||
key: "dropTheItem", | ||
value: function dropTheItem(place) { | ||
var _this$targetedNode2, _this$targetedNode2$p, _this$targetedNode3; | ||
updateCoordination(e) { | ||
this.calcMouseCoords(e); | ||
this.calcMouseToTargetedElDist(); | ||
} | ||
switch (place) { | ||
case 'before': | ||
(_this$targetedNode2 = this.targetedNode) === null || _this$targetedNode2 === void 0 ? void 0 : (_this$targetedNode2$p = _this$targetedNode2.parentNode) === null || _this$targetedNode2$p === void 0 ? void 0 : _this$targetedNode2$p.insertBefore(this.draggedNode, this.targetedNode); | ||
break; | ||
getDropLocation() { | ||
if (this.canBeDropped()) { | ||
if (this.targetedNode.nodeName === 'LI' && !this.cursorIsIndentedEnough()) return 'before' | ||
else if (this.targetedNode instanceof this.listInterface) return 'inside' | ||
case 'inside': | ||
(_this$targetedNode3 = this.targetedNode) === null || _this$targetedNode3 === void 0 ? void 0 : _this$targetedNode3.appendChild(this.draggedNode); | ||
break; | ||
} | ||
} | ||
} | ||
}, { | ||
key: "calcMouseCoords", | ||
value: function calcMouseCoords(e) { | ||
// we're having the client coords because on the next lines, we use getBoundingClientRect which behaves in the same way | ||
this.cursor = { | ||
X: e.clientX, | ||
Y: e.clientY | ||
}; | ||
} | ||
}, { | ||
key: "calcMouseToTargetedElDist", | ||
value: function calcMouseToTargetedElDist() { | ||
if (!this.targetedNode) { | ||
return; | ||
} | ||
maybeDrop(e) { | ||
const location = this.getDropLocation(); | ||
if (location) this.dropTheItem(location, e); | ||
} | ||
dropTheItem(place) { | ||
switch (place) { | ||
case 'before': | ||
this.targetedNode.parentNode.insertBefore(this.draggedNode, this.targetedNode); | ||
break | ||
case 'inside': | ||
this.targetedNode.appendChild(this.draggedNode); | ||
break | ||
var offset = this.targetedNode.getBoundingClientRect(); | ||
this.targetNode = { | ||
X: offset.left, | ||
Y: offset.top | ||
}; | ||
var result = this.targetNode.Y - this.cursor.Y; | ||
var targetedElTopAbs = Math.abs(result); | ||
this.distances.mouseTo = { | ||
targetedElTop: result, | ||
targetedElTopAbs: targetedElTopAbs, | ||
targetedElBot: targetedElTopAbs - this.targetedNode.clientHeight | ||
}; | ||
} | ||
} | ||
}, { | ||
key: "areNested", | ||
value: function areNested(child, parent) { | ||
return !!child && !!parent && Array.from(parent === null || parent === void 0 ? void 0 : parent.querySelectorAll('li')).some(function (li) { | ||
return li === child; | ||
}); | ||
} | ||
}, { | ||
key: "cursorIsIndentedEnough", | ||
value: function cursorIsIndentedEnough() { | ||
return this.cursor.X - this.targetNode.X > 50; | ||
} | ||
}, { | ||
key: "mouseIsTooCloseToTop", | ||
value: function mouseIsTooCloseToTop() { | ||
var _this$distances; | ||
calcMouseCoords(e) { | ||
// we're having the client coords because on the next lines, we use getBoundingClientRect which behaves in the same way | ||
this.cursor.X = e.clientX; | ||
this.cursor.Y = e.clientY; | ||
} | ||
calcMouseToTargetedElDist() { | ||
if (!this.targetedNode) { | ||
return | ||
if (!((_this$distances = this.distances) !== null && _this$distances !== void 0 && _this$distances.droppingEdge)) return false; | ||
return this.cursor.Y - this.targetNode.Y < this.distances.droppingEdge; | ||
} | ||
}, { | ||
key: "managePlaceholderLists", | ||
value: function managePlaceholderLists() { | ||
var _this3 = this; | ||
let offset = this.targetedNode.getBoundingClientRect(); | ||
this.targetNode.X = offset.left; | ||
this.targetNode.Y = offset.top; | ||
var actions = this.analysePlaceHolderSituation(); | ||
actions.forEach(function (action) { | ||
switch (action) { | ||
case 'add': | ||
_this3.cleanupPlaceholderLists(); | ||
let result = this.targetNode.Y - this.cursor.Y; | ||
this.distances.mouseTo.targetedElTop = result; | ||
this.distances.mouseTo.targetedElTopAbs = Math.abs(result); | ||
this.dimensions.targetedEl.H = this.targetedNode.clientHeight; | ||
this.distances.mouseTo.targetedElBot = this.distances.mouseTo.targetedElTopAbs - this.dimensions.targetedEl.H; | ||
} | ||
_this3.addPlaceholderList(); | ||
areNested(child, parent) { | ||
return parent && Array.from(parent.querySelectorAll('li')).some(li => li === child) | ||
} | ||
break; | ||
cursorIsIndentedEnough() { | ||
return this.cursor.X - this.targetNode.X > 50 | ||
} | ||
case 'cleanup': | ||
_this3.cleanupPlaceholderLists(); | ||
mouseIsTooCloseToTop() { | ||
return this.cursor.Y - this.targetNode.Y < this.distances.droppingEdge | ||
} | ||
break; | ||
} | ||
}); | ||
} | ||
}, { | ||
key: "targetedNodeIsPlaceholder", | ||
value: function targetedNodeIsPlaceholder() { | ||
return this.targetedNode instanceof this.listInterface && this.targetedNode.classList.contains(this.classNames.placeholder); | ||
} | ||
}, { | ||
key: "getTargetedNodeDepth", | ||
value: function getTargetedNodeDepth() { | ||
var depth = 0; | ||
var el = this.targetedNode; | ||
var list = this.getSortableList(); | ||
managePlaceholderLists(e) { | ||
while (list !== ((_el = el) === null || _el === void 0 ? void 0 : _el.parentElement)) { | ||
var _el, _el2, _el3; | ||
let actions = this.analysePlaceHolderSituation(e); | ||
if (((_el2 = el) === null || _el2 === void 0 ? void 0 : _el2.parentElement) instanceof this.listInterface) depth++; | ||
el = (_el3 = el) === null || _el3 === void 0 ? void 0 : _el3.parentElement; | ||
} | ||
actions.forEach(action => { | ||
switch (action) { | ||
case 'add': | ||
this.cleanupPlaceholderLists(); | ||
this.addPlaceholderList(); | ||
break | ||
case 'cleanup': | ||
this.cleanupPlaceholderLists(); | ||
break | ||
return depth; | ||
} | ||
}, { | ||
key: "nestingThresholdReached", | ||
value: function nestingThresholdReached() { | ||
if (this.nestingLevels < 0) return false; | ||
if (this.nestingLevels === 0) return true; | ||
return this.getTargetedNodeDepth() >= this.nestingLevels; | ||
} | ||
}, { | ||
key: "analysePlaceHolderSituation", | ||
value: function analysePlaceHolderSituation() { | ||
if (!this.targetedNode || this.areNested(this.targetedNode, this.draggedNode)) { | ||
return []; | ||
} | ||
}); | ||
} | ||
targetedNodeIsPlaceholder() { | ||
return this.targetedNode instanceof this.listInterface | ||
&& this.targetedNode.classList.contains(this.classNames.placeholder) | ||
} | ||
var actions = []; | ||
getTargetedNodeDepth() { | ||
let depth = 0; | ||
let el = this.targetedNode; | ||
const list = this.getSortableList(); | ||
if (!this.cursorIsIndentedEnough() || this.mouseIsTooCloseToTop()) { | ||
if (!this.targetedNodeIsPlaceholder()) { | ||
actions.push('cleanup'); | ||
} | ||
} else if (this.targetedNode !== this.draggedNode && this.targetedNode.nodeName === 'LI' && !this.targetedNode.querySelectorAll(this.getListTagName()).length && !this.nestingThresholdReached()) { | ||
actions.push('add'); | ||
} | ||
while (list !== el.parentElement) { | ||
if (el.parentElement instanceof this.listInterface) depth++; | ||
el = el.parentElement; | ||
return actions; | ||
} | ||
}, { | ||
key: "animatePlaceholderList", | ||
value: function animatePlaceholderList() { | ||
var _this$draggedNode; | ||
return depth | ||
} | ||
this.placeholderInUse.style.minHeight = '0'; | ||
this.placeholderInUse.style.transition = 'min-height ease .2s'; | ||
this.placeholderInUse.style.minHeight = "".concat((_this$draggedNode = this.draggedNode) === null || _this$draggedNode === void 0 ? void 0 : _this$draggedNode.offsetHeight, "px"); | ||
} | ||
}, { | ||
key: "addPlaceholderList", | ||
value: function addPlaceholderList() { | ||
var _this$targetedNode4; | ||
nestingThresholdReached() { | ||
if (this.nestingLevels < 0) return false | ||
if (this.nestingLevels === 0) return true | ||
this.getPlaceholderList(); | ||
(_this$targetedNode4 = this.targetedNode) === null || _this$targetedNode4 === void 0 ? void 0 : _this$targetedNode4.appendChild(this.placeholderInUse); | ||
this.animatePlaceholderList(); | ||
} | ||
}, { | ||
key: "targetNodeIsIdentified", | ||
value: function targetNodeIsIdentified() { | ||
return !!this.targetedNode; | ||
} | ||
}, { | ||
key: "targetNodeIsBeingDragged", | ||
value: function targetNodeIsBeingDragged() { | ||
return this.targetNodeIsIdentified() && this.targetedNode === this.draggedNode; | ||
} | ||
}, { | ||
key: "targetNodeIsListWithItems", | ||
value: function targetNodeIsListWithItems() { | ||
return this.targetNodeIsIdentified() && this.targetedNode instanceof this.listInterface && !!this.targetedNode.querySelectorAll('li').length; | ||
} | ||
}, { | ||
key: "canBeDropped", | ||
value: function canBeDropped() { | ||
return this.targetNodeIsIdentified() && !this.targetNodeIsBeingDragged() && !this.targetNodeIsListWithItems() && !this.areNested(this.targetedNode, this.draggedNode); | ||
} | ||
}, { | ||
key: "cleanupPlaceholderLists", | ||
value: function cleanupPlaceholderLists() { | ||
var _this$getSortableList2, | ||
_this4 = this; | ||
return this.getTargetedNodeDepth() >= this.nestingLevels | ||
} | ||
analysePlaceHolderSituation() { | ||
if (!this.targetedNode || this.areNested(this.targetedNode, this.draggedNode)) { | ||
return [] | ||
var tag = this.getListTagName(); | ||
var listsArray = ((_this$getSortableList2 = this.getSortableList()) === null || _this$getSortableList2 === void 0 ? void 0 : _this$getSortableList2.querySelectorAll(tag)) || []; | ||
Array.from(listsArray).forEach(function (ul) { | ||
if (!ul.querySelectorAll('li').length) { | ||
ul.remove(); | ||
} else if (ul.classList.contains(_this4.classNames.placeholder)) { | ||
ul.classList.remove(_this4.classNames.placeholder); | ||
ul.style.minHeight = 'auto'; | ||
ul.dataset.id = ul.parentNode.dataset.id; | ||
} | ||
}); | ||
} | ||
}, { | ||
key: "initPlaceholderList", | ||
value: function initPlaceholderList() { | ||
var _this$placeholderList; | ||
let actions = []; | ||
this.placeholderList = document.createElement(this.getListTagName()); | ||
if (!this.cursorIsIndentedEnough() || this.mouseIsTooCloseToTop()) { | ||
if (!this.targetedNodeIsPlaceholder()) { | ||
actions.push('cleanup'); | ||
} | ||
} else if (this.targetedNode !== this.draggedNode | ||
&& this.targetedNode.nodeName === 'LI' | ||
&& !this.targetedNode.querySelectorAll(this.getListTagName()).length | ||
&& !this.nestingThresholdReached()) { | ||
actions.push('add'); | ||
(_this$placeholderList = this.placeholderList.classList).add.apply(_this$placeholderList, [this.classNames.placeholder].concat(_toConsumableArray(this.listClassNames))); | ||
} | ||
}, { | ||
key: "getPlaceholderList", | ||
value: function getPlaceholderList() { | ||
this.placeholderInUse = this.placeholderList.cloneNode(true); | ||
return this.placeholderInUse; | ||
} | ||
}]); | ||
return actions | ||
} | ||
return NestedSort; | ||
}(); | ||
animatePlaceholderList() { | ||
this.placeholderInUse.style.minHeight = '0'; | ||
this.placeholderInUse.style.transition = 'min-height ease .2s'; | ||
this.placeholderInUse.style.minHeight = `${this.draggedNode.offsetHeight}px`; | ||
} | ||
addPlaceholderList() { | ||
this.getPlaceholderList(); | ||
this.targetedNode.appendChild(this.placeholderInUse); | ||
this.animatePlaceholderList(); | ||
} | ||
targetNodeIsIdentified() { | ||
return !!this.targetedNode | ||
} | ||
targetNodeIsBeingDragged() { | ||
return this.targetNodeIsIdentified() | ||
&& this.targetedNode === this.draggedNode | ||
} | ||
targetNodeIsListWithItems() { | ||
return this.targetNodeIsIdentified() | ||
&& this.targetedNode instanceof this.listInterface | ||
&& this.targetedNode.querySelectorAll('li').length | ||
} | ||
canBeDropped() { | ||
return this.targetNodeIsIdentified() | ||
&& !this.targetNodeIsBeingDragged() | ||
&& !this.targetNodeIsListWithItems() | ||
&& !this.areNested(this.targetedNode, this.draggedNode) | ||
} | ||
cleanupPlaceholderLists() { | ||
this.getSortableList().querySelectorAll(this.getListTagName()).forEach(ul => { | ||
if (!ul.querySelectorAll('li').length) { | ||
ul.remove(); | ||
} else if (ul.classList.contains(this.classNames.placeholder)) { | ||
ul.classList.remove(this.classNames.placeholder); | ||
ul.style.minHeight = 'auto'; | ||
ul.dataset.id = ul.parentNode.dataset.id; | ||
} | ||
}); | ||
} | ||
initPlaceholderList() { | ||
this.placeholderList = document.createElement(this.getListTagName()); | ||
this.placeholderList.classList.add(this.classNames.placeholder, ...this.listClassNames); | ||
} | ||
getPlaceholderList() { | ||
this.placeholderInUse = this.placeholderList.cloneNode(true); | ||
return this.placeholderInUse | ||
} | ||
} | ||
module.exports = NestedSort; |
@@ -1,8 +0,90 @@ | ||
class DataEngine { | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
} | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
} | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _toConsumableArray(arr) { | ||
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); | ||
} | ||
function _arrayWithoutHoles(arr) { | ||
if (Array.isArray(arr)) return _arrayLikeToArray(arr); | ||
} | ||
function _iterableToArray(iter) { | ||
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); | ||
} | ||
function _unsupportedIterableToArray(o, minLen) { | ||
if (!o) return; | ||
if (typeof o === "string") return _arrayLikeToArray(o, minLen); | ||
var n = Object.prototype.toString.call(o).slice(8, -1); | ||
if (n === "Object" && o.constructor) n = o.constructor.name; | ||
if (n === "Map" || n === "Set") return Array.from(o); | ||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); | ||
} | ||
function _arrayLikeToArray(arr, len) { | ||
if (len == null || len > arr.length) len = arr.length; | ||
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; | ||
return arr2; | ||
} | ||
function _nonIterableSpread() { | ||
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); | ||
} | ||
var DataEngine = /*#__PURE__*/function () { | ||
/** | ||
* @constructor | ||
* @param {object[]} [data] | ||
* @param {object} [propertyMap={}] | ||
*/ | ||
constructor({ data, propertyMap = {} }) { | ||
function DataEngine(_ref) { | ||
var data = _ref.data, | ||
_ref$propertyMap = _ref.propertyMap, | ||
propertyMap = _ref$propertyMap === void 0 ? {} : _ref$propertyMap; | ||
_classCallCheck(this, DataEngine); | ||
_defineProperty(this, "data", void 0); | ||
_defineProperty(this, "sortedData", void 0); | ||
_defineProperty(this, "sortedDataDomArray", void 0); | ||
_defineProperty(this, "propertyMap", void 0); | ||
this.data = data; | ||
@@ -12,48 +94,47 @@ this.sortedData = []; | ||
this.propertyMap = propertyMap; | ||
this.maybeTransformData(); | ||
} | ||
maybeTransformData() { | ||
if (!Object.keys(this.propertyMap).length || !Array.isArray(this.data)) return | ||
_createClass(DataEngine, [{ | ||
key: "maybeTransformData", | ||
value: function maybeTransformData() { | ||
if (!Object.keys(this.propertyMap).length || !Array.isArray(this.data)) return; | ||
var getItemPropProxyName = this.getItemPropProxyName.bind(this); | ||
this.data = this.data.map(function (item) { | ||
return new Proxy(item, { | ||
get: function get(target, prop, receiver) { | ||
return Reflect.get(target, getItemPropProxyName(prop), receiver); | ||
} | ||
}); | ||
}); | ||
} | ||
}, { | ||
key: "getItemPropProxyName", | ||
value: function getItemPropProxyName(prop) { | ||
if (Object.prototype.hasOwnProperty.call(this.propertyMap, prop)) { | ||
return this.propertyMap[prop]; | ||
} | ||
const getItemPropProxyName = this.getItemPropProxyName.bind(this); | ||
this.data = this.data.map(item => { | ||
return new Proxy(item, { | ||
get(target, prop, receiver) { | ||
return Reflect.get(target, getItemPropProxyName(prop), receiver) | ||
}, | ||
}) | ||
}); | ||
} | ||
/** | ||
* @param {PropertyKey} prop | ||
* @returns {PropertyKey} | ||
*/ | ||
getItemPropProxyName(prop) { | ||
if (Object.prototype.hasOwnProperty.call(this.propertyMap, prop)) { | ||
return this.propertyMap[prop] | ||
return prop; | ||
} | ||
return prop | ||
} | ||
}, { | ||
key: "isTopLevelItem", | ||
value: function isTopLevelItem(item) { | ||
return !item.parent; | ||
} | ||
}, { | ||
key: "sortListItems", | ||
value: function sortListItems() { | ||
var _this = this; | ||
isTopLevelItem(item) { | ||
return !item.parent | ||
} | ||
var items = _toConsumableArray(this.data); | ||
/** | ||
* @returns {object[]} | ||
*/ | ||
sortListItems() { | ||
const items = [...this.data]; | ||
const topLevelItems = items | ||
.filter(a => this.isTopLevelItem(a)) | ||
.sort((a, b) => a.order && b.order ? a.order - b.order : 0); | ||
const childItems = items | ||
.filter(a => !this.isTopLevelItem(a)) | ||
.reduce((groups, item) => { | ||
var topLevelItems = items.filter(function (a) { | ||
return _this.isTopLevelItem(a); | ||
}).sort(function (a, b) { | ||
return a.order && b.order ? a.order - b.order : 0; | ||
}); | ||
var childItems = items.filter(function (a) { | ||
return !_this.isTopLevelItem(a); | ||
}).reduce(function (groups, item) { | ||
if (Object.prototype.hasOwnProperty.call(groups, item.parent)) { | ||
@@ -64,184 +145,195 @@ groups[item.parent].push(item); | ||
} | ||
return groups | ||
return groups; | ||
}, {}); | ||
Object.keys(childItems).forEach(function (parentId) { | ||
childItems[parentId].sort(function (a, b) { | ||
return a.order && b.order ? a.order - b.order : 0; | ||
}); | ||
}); | ||
this.sortedData = [].concat(_toConsumableArray(topLevelItems), _toConsumableArray(Object.values(childItems).flat())); | ||
return this.sortedData; | ||
} | ||
}, { | ||
key: "createItemElement", | ||
value: function createItemElement(item) { | ||
var nodeName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'li'; | ||
var id = item.id, | ||
text = item.text; | ||
var el = document.createElement(nodeName); | ||
el.dataset.id = id; | ||
if (nodeName === 'li' && text) el.innerHTML = text; | ||
return el; | ||
} | ||
}, { | ||
key: "elementIsParentOfItem", | ||
value: function elementIsParentOfItem(node, item) { | ||
return node.dataset.id === "".concat(item.parent); | ||
} | ||
}, { | ||
key: "getParentNodeOfItem", | ||
value: function getParentNodeOfItem(node, item, nodeName) { | ||
return node.querySelector("".concat(nodeName, "[data-id=\"").concat(item.parent, "\"]")); | ||
} | ||
}, { | ||
key: "elementIsAncestorOfItem", | ||
value: function elementIsAncestorOfItem(node, item) { | ||
return !!this.getParentNodeOfItem(node, item, 'li'); | ||
} | ||
}, { | ||
key: "getDirectListParentOfItem", | ||
value: function getDirectListParentOfItem(node, item) { | ||
return this.getParentNodeOfItem(node, item, 'ol'); | ||
} | ||
}, { | ||
key: "maybeAppendItemToParentDom", | ||
value: function maybeAppendItemToParentDom(item) { | ||
var _this2 = this; | ||
Object.keys(childItems).forEach(parentId => { | ||
childItems[parentId].sort((a, b) => a.order && b.order ? a.order - b.order : 0); | ||
}); | ||
var parent = item.parent; | ||
var topParent = this.sortedDataDomArray.find(function (topLevelListItem) { | ||
return _this2.elementIsParentOfItem(topLevelListItem, item) || _this2.elementIsAncestorOfItem(topLevelListItem, item); | ||
}); | ||
if (!topParent) return false; | ||
var listItem = this.createItemElement(item); | ||
var directParentList = this.getDirectListParentOfItem(topParent, item); | ||
this.sortedData = [ | ||
...topLevelItems, | ||
...Object.values(childItems).flat(), | ||
]; | ||
if (!directParentList) { | ||
// we need to create the direct parent OL and append it to the direct parent LI | ||
directParentList = this.createItemElement({ | ||
id: parent | ||
}, 'ol'); | ||
var directParentListItem = this.getParentNodeOfItem(topParent, item, 'li') || topParent; | ||
directParentListItem.appendChild(directParentList); | ||
} | ||
return this.sortedData | ||
} | ||
directParentList.appendChild(listItem); | ||
return true; | ||
} | ||
}, { | ||
key: "getListItemsDom", | ||
value: function getListItemsDom() { | ||
var _this3 = this; | ||
/** | ||
* @param {object[]} item | ||
* @param {string} nodeName | ||
* @returns {HTMLElement} | ||
*/ | ||
createItemElement(item, nodeName = 'li') { | ||
const { id, text } = item; | ||
const el = document.createElement(nodeName); | ||
el.dataset.id = id; | ||
if (nodeName === 'li') el.innerHTML = text; | ||
this.sortedDataDomArray = []; | ||
var processedItems = []; | ||
return el | ||
} | ||
while (processedItems.length !== this.sortListItems().length) { | ||
processedItems = this.sortedData.reduce(function (processedItems, item) { | ||
var id = item.id.toString(); | ||
if (processedItems.includes(id)) return processedItems; | ||
var itemAdded; | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
elementIsParentOfItem(node, item) { | ||
return node.dataset.id === `${item.parent}` | ||
} | ||
if (!item.parent) { | ||
var listItem = _this3.createItemElement(item); | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @param {string} nodeName | ||
* @returns {Element|null} | ||
*/ | ||
getParentNodeOfItem(node, item, nodeName) { | ||
return node.querySelector(`${nodeName}[data-id="${item.parent}"]`) | ||
} | ||
_this3.sortedDataDomArray.push(listItem); | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
elementIsAncestorOfItem(node, item) { | ||
return !!this.getParentNodeOfItem(node, item, 'li') | ||
} | ||
itemAdded = true; | ||
} else { | ||
itemAdded = _this3.maybeAppendItemToParentDom(item); | ||
} | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {HTMLElement} | ||
*/ | ||
getDirectListParentOfItem(node, item) { | ||
return this.getParentNodeOfItem(node, item, 'ol') | ||
} | ||
if (itemAdded) processedItems.push(id); | ||
return processedItems; | ||
}, processedItems); | ||
} | ||
/** | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
maybeAppendItemToParentDom(item) { | ||
const { parent } = item; | ||
const topParent = this.sortedDataDomArray.find(topLevelListItem => { | ||
return this.elementIsParentOfItem(topLevelListItem, item) || this.elementIsAncestorOfItem(topLevelListItem, item) | ||
}); | ||
return this.sortedDataDomArray; | ||
} | ||
}, { | ||
key: "convertDomToData", | ||
value: function convertDomToData(list) { | ||
var _this4 = this; | ||
if (!topParent) return false | ||
return Array.from((list === null || list === void 0 ? void 0 : list.querySelectorAll('li')) || []).map(function (li) { | ||
var _ref2; | ||
const listItem = this.createItemElement(item); | ||
let directParentList = this.getDirectListParentOfItem(topParent, item); | ||
if (!directParentList) { | ||
// we need to create the direct parent OL and append it to the direct parent LI | ||
directParentList = this.createItemElement({ id: parent }, 'ol'); | ||
const directParentListItem = this.getParentNodeOfItem(topParent, item, 'li') || topParent; | ||
directParentListItem.appendChild(directParentList); | ||
var parentListItem = li.parentNode; | ||
var parent = parentListItem.dataset.id; | ||
var order = Array.from(parentListItem.children).findIndex(function (item) { | ||
return item === li; | ||
}) + 1; | ||
return _ref2 = {}, _defineProperty(_ref2, _this4.getItemPropProxyName('id'), li.dataset.id), _defineProperty(_ref2, _this4.getItemPropProxyName('parent'), parent), _defineProperty(_ref2, _this4.getItemPropProxyName('order'), order), _ref2; | ||
}); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var list = document.createElement('ol'); | ||
this.getListItemsDom().forEach(function (listItem) { | ||
return list.appendChild(listItem); | ||
}); | ||
return list; | ||
} | ||
}]); | ||
directParentList.appendChild(listItem); | ||
return DataEngine; | ||
}(); | ||
return true | ||
} | ||
var NestedSort = /*#__PURE__*/function () { | ||
function NestedSort(_ref) { | ||
var _ref$actions = _ref.actions, | ||
actions = _ref$actions === void 0 ? {} : _ref$actions, | ||
data = _ref.data, | ||
_ref$droppingEdge = _ref.droppingEdge, | ||
droppingEdge = _ref$droppingEdge === void 0 ? 15 : _ref$droppingEdge, | ||
el = _ref.el, | ||
_ref$init = _ref.init, | ||
init = _ref$init === void 0 ? true : _ref$init, | ||
listClassNames = _ref.listClassNames, | ||
listItemClassNames = _ref.listItemClassNames, | ||
nestingLevels = _ref.nestingLevels, | ||
_ref$propertyMap = _ref.propertyMap, | ||
propertyMap = _ref$propertyMap === void 0 ? {} : _ref$propertyMap; | ||
/** | ||
* @returns {array} | ||
*/ | ||
getListItemsDom() { | ||
this.sortedDataDomArray = []; | ||
let processedItems = []; | ||
_classCallCheck(this, NestedSort); | ||
while (processedItems.length !== this.sortListItems().length) { | ||
processedItems = this.sortedData.reduce((processedItems, item) => { | ||
const { id } = item; | ||
if (processedItems.includes(id)) return processedItems | ||
_defineProperty(this, "actions", void 0); | ||
let itemAdded; | ||
if (!item.parent) { | ||
const listItem = this.createItemElement(item); | ||
this.sortedDataDomArray.push(listItem); | ||
itemAdded = true; | ||
} else { | ||
itemAdded = this.maybeAppendItemToParentDom(item); | ||
} | ||
_defineProperty(this, "classNames", void 0); | ||
if (itemAdded) processedItems.push(id); | ||
_defineProperty(this, "cursor", void 0); | ||
return processedItems | ||
}, processedItems); | ||
} | ||
_defineProperty(this, "data", void 0); | ||
return this.sortedDataDomArray | ||
} | ||
_defineProperty(this, "dataEngine", void 0); | ||
/** | ||
* @param {HTMLOListElement|HTMLUListElement} list | ||
* @returns {object[]} | ||
*/ | ||
convertDomToData(list) { | ||
return Array.from(list.querySelectorAll('li')).map(li => { | ||
const parentListItem = li.parentNode; | ||
const parent = parentListItem.dataset.id; | ||
const order = Array.from(parentListItem.children).findIndex(item => item === li) + 1; | ||
_defineProperty(this, "distances", void 0); | ||
return { | ||
[this.getItemPropProxyName('id')]: li.dataset.id, | ||
[this.getItemPropProxyName('parent')]: parent, | ||
[this.getItemPropProxyName('order')]: order, | ||
} | ||
}) | ||
} | ||
_defineProperty(this, "draggedNode", void 0); | ||
/** | ||
* @returns {HTMLOListElement} | ||
*/ | ||
render() { | ||
const list = document.createElement('ol'); | ||
this.getListItemsDom().forEach(listItem => list.appendChild(listItem)); | ||
return list | ||
} | ||
} | ||
_defineProperty(this, "initialised", void 0); | ||
class NestedSort { | ||
/** | ||
* @constructor | ||
* @param {object} [actions={}] | ||
* @param {array} [data] | ||
* @param {number} [droppingEdge=15] | ||
* @param {string|HTMLElement} el | ||
* @param {boolean} [init=true] | ||
* @param {array|string} [listClassNames] | ||
* @param {array|string} [listItemClassNames] | ||
* @param {number|string} [nestingLevels] | ||
* @param {object} [propertyMap={}] | ||
*/ | ||
constructor({ | ||
actions: { onDrop } = {}, | ||
data, | ||
droppingEdge = 15, | ||
el, | ||
init = true, | ||
listClassNames, | ||
listItemClassNames, | ||
nestingLevels, | ||
propertyMap = {}, | ||
}) { | ||
_defineProperty(this, "listClassNames", void 0); | ||
_defineProperty(this, "listEventListeners", void 0); | ||
_defineProperty(this, "listInterface", void 0); | ||
_defineProperty(this, "listItemClassNames", void 0); | ||
_defineProperty(this, "mainListClassName", void 0); | ||
_defineProperty(this, "nestingLevels", void 0); | ||
_defineProperty(this, "placeholderList", void 0); | ||
_defineProperty(this, "placeholderInUse", void 0); | ||
_defineProperty(this, "propertyMap", void 0); | ||
_defineProperty(this, "sortableList", void 0); | ||
_defineProperty(this, "targetedNode", void 0); | ||
_defineProperty(this, "targetNode", void 0); | ||
_defineProperty(this, "wrapper", void 0); | ||
var element = typeof el === 'string' ? document.querySelector(el) : el; | ||
var elementIsAList = element instanceof HTMLOListElement || element instanceof HTMLUListElement; | ||
this.wrapper = elementIsAList ? undefined : element; | ||
this.sortableList = elementIsAList ? element : null; | ||
this.data = data; | ||
this.selector = el; | ||
this.sortableList = null; | ||
this.placeholderList = null; | ||
this.placeholderInUse = null; | ||
this.draggedNode = null; | ||
this.targetedNode = null; | ||
this.listClassNames = this.createListClassNamesArray(listClassNames); | ||
@@ -252,29 +344,12 @@ this.mainListClassName = this.listClassNames[0] || 'nested-sort'; | ||
this.actions = { | ||
onDrop, | ||
onDrop: actions.onDrop | ||
}; | ||
this.initialised = false; | ||
this.targetNode = { | ||
X: null, | ||
Y: null, | ||
}; | ||
this.distances = { | ||
droppingEdge, | ||
droppingEdgeNegative: droppingEdge * -1, | ||
mouseTo: { | ||
targetedElTop: undefined, | ||
}, | ||
droppingEdge: droppingEdge | ||
}; | ||
this.dimensions = { | ||
targetedEl: { | ||
H: undefined, | ||
}, | ||
}; | ||
this.cursor = { | ||
X: null, | ||
Y: null, | ||
}; | ||
this.classNames = { | ||
dragged: 'ns-dragged', | ||
placeholder: 'ns-placeholder', | ||
targeted: 'ns-targeted', | ||
targeted: 'ns-targeted' | ||
}; | ||
@@ -286,8 +361,8 @@ this.listEventListeners = { | ||
dragend: this.onDragEnd.bind(this), | ||
drop: this.onDrop.bind(this), | ||
drop: this.onDrop.bind(this) | ||
}; | ||
const intNestingLevels = parseInt(nestingLevels); | ||
var intNestingLevels = parseInt(nestingLevels); | ||
this.nestingLevels = isNaN(intNestingLevels) ? -1 : intNestingLevels; // values less than 0 mean infinite levels of nesting | ||
this.listInterface = this.getListInterface(); | ||
this.maybeInitDataDom(); | ||
@@ -298,344 +373,411 @@ this.addListAttributes(); | ||
getListInterface() { | ||
if (Array.isArray(this.data) && this.data.length) return HTMLOListElement | ||
_createClass(NestedSort, [{ | ||
key: "getListInterface", | ||
value: function getListInterface() { | ||
if (Array.isArray(this.data) && this.data.length) return HTMLOListElement; | ||
return this.sortableList instanceof HTMLOListElement ? HTMLOListElement : HTMLUListElement; | ||
} | ||
}, { | ||
key: "getDataEngine", | ||
value: function getDataEngine() { | ||
if (this.dataEngine) return this.dataEngine; | ||
this.dataEngine = new DataEngine({ | ||
data: this.data, | ||
propertyMap: this.propertyMap | ||
}); | ||
return this.dataEngine; | ||
} | ||
}, { | ||
key: "createListClassNamesArray", | ||
value: function createListClassNamesArray(listClassNames) { | ||
if (!listClassNames) return []; | ||
return Array.isArray(listClassNames) ? listClassNames : listClassNames.split(' '); | ||
} | ||
}, { | ||
key: "maybeInitDataDom", | ||
value: function maybeInitDataDom() { | ||
if (!(Array.isArray(this.data) && this.data.length && this.wrapper)) return; | ||
var list = this.getDataEngine().render(); | ||
this.wrapper.innerHTML = ''; | ||
this.wrapper.appendChild(list); | ||
} | ||
}, { | ||
key: "getListTagName", | ||
value: function getListTagName() { | ||
return this.listInterface === HTMLOListElement ? 'ol' : 'ul'; | ||
} | ||
}, { | ||
key: "getSortableList", | ||
value: function getSortableList() { | ||
var _this$wrapper; | ||
const el = this.selector instanceof HTMLElement | ||
? this.selector | ||
: document.querySelector(this.selector); | ||
return el instanceof HTMLOListElement ? HTMLOListElement : HTMLUListElement | ||
} | ||
getDataEngine() { | ||
if (this.dataEngine instanceof DataEngine) { | ||
return this.dataEngine | ||
if (this.sortableList instanceof this.listInterface) return this.sortableList; | ||
this.sortableList = (_this$wrapper = this.wrapper) === null || _this$wrapper === void 0 ? void 0 : _this$wrapper.querySelector(this.getListTagName()); | ||
return this.sortableList; | ||
} | ||
this.dataEngine = new DataEngine({data: this.data, propertyMap: this.propertyMap}); | ||
return this.dataEngine | ||
} | ||
}, { | ||
key: "addListAttributes", | ||
value: function addListAttributes() { | ||
var _list$classList, | ||
_this = this; | ||
createListClassNamesArray(listClassNames) { | ||
if (!listClassNames) return [] | ||
return Array.isArray(listClassNames) ? listClassNames : listClassNames.split(' ') | ||
} | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
maybeInitDataDom() { | ||
if (!(Array.isArray(this.data) && this.data.length)) return | ||
(_list$classList = list.classList).add.apply(_list$classList, _toConsumableArray(this.listClassNames.concat(this.mainListClassName))); | ||
const wrapper = document.querySelector(this.selector); | ||
const list = this.getDataEngine().render(); | ||
wrapper.innerHTML = ''; | ||
wrapper.appendChild(list); | ||
} | ||
list.querySelectorAll(this.getListTagName()).forEach(function (l) { | ||
var _l$classList; | ||
getListTagName() { | ||
return this.listInterface === HTMLOListElement ? 'ol' : 'ul' | ||
} | ||
(_l$classList = l.classList).add.apply(_l$classList, _toConsumableArray(_this.listClassNames)); | ||
}); | ||
list.querySelectorAll('li').forEach(function (li) { | ||
var _li$classList; | ||
getSortableList() { | ||
if (this.sortableList instanceof this.listInterface) return this.sortableList | ||
(_li$classList = li.classList).add.apply(_li$classList, _toConsumableArray(_this.listItemClassNames)); | ||
}); | ||
} | ||
}, { | ||
key: "toggleMainListLifeCycleClassName", | ||
value: function toggleMainListLifeCycleClassName() { | ||
var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
var className = "".concat(this.mainListClassName, "--enabled"); | ||
enabled ? list.classList.add(className) : list.classList.remove(className); | ||
} | ||
}, { | ||
key: "toggleListItemAttributes", | ||
value: function toggleListItemAttributes() { | ||
var _this$getSortableList; | ||
if (this.selector instanceof this.listInterface) { | ||
this.sortableList = this.selector; | ||
} else { | ||
const list = document.querySelector(this.selector); | ||
this.sortableList = list instanceof this.listInterface | ||
? list | ||
: list.querySelector(this.getListTagName()); | ||
var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
(_this$getSortableList = this.getSortableList()) === null || _this$getSortableList === void 0 ? void 0 : _this$getSortableList.querySelectorAll('li').forEach(function (el) { | ||
el.setAttribute('draggable', enable.toString()); | ||
}); | ||
} | ||
}, { | ||
key: "toggleListEventListeners", | ||
value: function toggleListEventListeners() { | ||
var _this2 = this; | ||
return this.sortableList | ||
} | ||
var remove = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
Object.keys(this.listEventListeners).forEach(function (event) { | ||
remove ? list.removeEventListener(event, _this2.listEventListeners[event]) : list.addEventListener(event, _this2.listEventListeners[event], false); | ||
}); | ||
} | ||
}, { | ||
key: "initDragAndDrop", | ||
value: function initDragAndDrop() { | ||
if (this.initialised) return; | ||
this.toggleListEventListeners(); | ||
this.initPlaceholderList(); | ||
this.toggleListItemAttributes(); | ||
this.toggleMainListLifeCycleClassName(); | ||
this.initialised = true; | ||
} | ||
}, { | ||
key: "init", | ||
value: function init() { | ||
this.initDragAndDrop(); | ||
} | ||
}, { | ||
key: "destroy", | ||
value: function destroy() { | ||
this.toggleListEventListeners(true); | ||
this.toggleListItemAttributes(false); | ||
this.toggleMainListLifeCycleClassName(false); | ||
this.initialised = false; | ||
} | ||
}, { | ||
key: "removeClassFromEl", | ||
value: function removeClassFromEl(className, el) { | ||
if (el && el.classList.contains(className)) { | ||
el.classList.remove(className); | ||
} | ||
} | ||
}, { | ||
key: "canBeTargeted", | ||
value: function canBeTargeted(el) { | ||
if (!this.draggedNode || this.draggedNode === el) return false; | ||
return el.nodeName === 'LI' || el instanceof this.listInterface && el.classList.contains(this.classNames.placeholder); | ||
} | ||
}, { | ||
key: "onDragStart", | ||
value: function onDragStart(e) { | ||
var _e$dataTransfer; | ||
addListAttributes() { | ||
const list = this.getSortableList(); | ||
this.draggedNode = e.target; | ||
this.draggedNode.classList.add(this.classNames.dragged); | ||
(_e$dataTransfer = e.dataTransfer) === null || _e$dataTransfer === void 0 ? void 0 : _e$dataTransfer.setData('text', 'Drag started!'); // Hack for Firefox! | ||
} | ||
}, { | ||
key: "onDragOver", | ||
value: function onDragOver(e) { | ||
e.preventDefault(); // prevent default to allow drop | ||
list.classList.add(...this.listClassNames.concat(this.mainListClassName)); | ||
list.querySelectorAll(this.getListTagName()).forEach(l => { | ||
l.classList.add(...this.listClassNames); | ||
}); | ||
this.updateCoordination(e); | ||
this.managePlaceholderLists(); | ||
} | ||
}, { | ||
key: "onDragEnter", | ||
value: function onDragEnter(e) { | ||
if (!this.canBeTargeted(e.target)) return; | ||
this.removeClassFromEl(this.classNames.targeted, this.targetedNode); | ||
this.targetedNode = e.target; | ||
this.targetedNode.classList.add(this.classNames.targeted); | ||
} | ||
}, { | ||
key: "onDragEnd", | ||
value: function onDragEnd(e) { | ||
e.stopPropagation(); | ||
this.removeClassFromEl(this.classNames.dragged, this.draggedNode); | ||
this.removeClassFromEl(this.classNames.targeted, this.targetedNode); | ||
this.cleanupPlaceholderLists(); | ||
delete this.draggedNode; | ||
delete this.targetedNode; | ||
} | ||
}, { | ||
key: "onDrop", | ||
value: function onDrop(e) { | ||
e.stopPropagation(); | ||
this.maybeDrop(); | ||
this.cleanupPlaceholderLists(); | ||
list.querySelectorAll('li').forEach(li => { | ||
li.classList.add(...this.listItemClassNames); | ||
}); | ||
} | ||
toggleMainListLifeCycleClassName(enabled = true) { | ||
const className = `${this.mainListClassName}--enabled`; | ||
const classList = this.getSortableList().classList; | ||
return enabled | ||
? classList.add(className) | ||
: classList.remove(className) | ||
} | ||
toggleListItemAttributes(enable = true) { | ||
this.getSortableList().querySelectorAll('li').forEach(el => { | ||
el.setAttribute('draggable', enable); | ||
}); | ||
} | ||
toggleListEventListeners(remove = false) { | ||
const list = this.getSortableList(); | ||
Object.keys(this.listEventListeners).forEach(event => { | ||
if (remove) { | ||
list.removeEventListener(event, this.listEventListeners[event]); | ||
} else { | ||
list.addEventListener(event, this.listEventListeners[event], false); | ||
if (typeof this.actions.onDrop === 'function') { | ||
this.actions.onDrop(this.getDataEngine().convertDomToData(this.getSortableList())); | ||
} | ||
}); | ||
} | ||
initDragAndDrop() { | ||
if (this.initialised) return | ||
this.toggleListEventListeners(); | ||
this.initPlaceholderList(); | ||
this.toggleListItemAttributes(); | ||
this.toggleMainListLifeCycleClassName(); | ||
this.initialised = true; | ||
} | ||
init() { | ||
this.initDragAndDrop(); | ||
} | ||
destroy() { | ||
this.toggleListEventListeners(true); | ||
this.toggleListItemAttributes(false); | ||
this.toggleMainListLifeCycleClassName(false); | ||
this.initialised = false; | ||
} | ||
removeClassFromEl(el, className) { | ||
if (el && el.classList.contains(className)) { | ||
el.classList.remove(className); | ||
} | ||
} | ||
}, { | ||
key: "updateCoordination", | ||
value: function updateCoordination(e) { | ||
this.calcMouseCoords(e); | ||
this.calcMouseToTargetedElDist(); | ||
} | ||
}, { | ||
key: "getDropLocation", | ||
value: function getDropLocation() { | ||
if (this.canBeDropped()) { | ||
var _this$targetedNode; | ||
canBeTargeted(el) { | ||
if (!this.draggedNode || this.draggedNode === el) return false | ||
return el.nodeName === 'LI' || (el instanceof this.listInterface && el.classList.contains(this.classNames.placeholder)) | ||
} | ||
onDragStart(e) { | ||
this.draggedNode = e.target; | ||
this.draggedNode.classList.add(this.classNames.dragged); | ||
e.dataTransfer.setData('text', 'Drag started!'); // Hack for Firefox! | ||
} | ||
onDragOver(e) { | ||
e.preventDefault(); // prevent default to allow drop | ||
this.updateCoordination(e); | ||
this.managePlaceholderLists(e); | ||
} | ||
onDragEnter(e) { | ||
if (!this.canBeTargeted(e.target)) return | ||
this.removeClassFromEl(this.targetedNode, this.classNames.targeted); | ||
this.targetedNode = e.target; | ||
this.targetedNode.classList.add(this.classNames.targeted); | ||
} | ||
onDragEnd(e) { | ||
e.stopPropagation(); | ||
this.removeClassFromEl(this.draggedNode, this.classNames.dragged); | ||
this.removeClassFromEl(this.targetedNode, this.classNames.targeted); | ||
this.cleanupPlaceholderLists(); | ||
this.draggedNode = null; | ||
this.targetedNode = null; | ||
} | ||
onDrop(e) { | ||
e.stopPropagation(); | ||
this.maybeDrop(); | ||
this.cleanupPlaceholderLists(); | ||
if (typeof this.actions.onDrop === 'function') { | ||
this.actions.onDrop(this.getDataEngine().convertDomToData(this.getSortableList())); | ||
if (((_this$targetedNode = this.targetedNode) === null || _this$targetedNode === void 0 ? void 0 : _this$targetedNode.nodeName) === 'LI') return 'before';else if (this.targetedNode instanceof this.listInterface) return 'inside'; | ||
} | ||
} | ||
} | ||
}, { | ||
key: "maybeDrop", | ||
value: function maybeDrop() { | ||
var location = this.getDropLocation(); | ||
if (location) this.dropTheItem(location); | ||
} | ||
}, { | ||
key: "dropTheItem", | ||
value: function dropTheItem(place) { | ||
var _this$targetedNode2, _this$targetedNode2$p, _this$targetedNode3; | ||
updateCoordination(e) { | ||
this.calcMouseCoords(e); | ||
this.calcMouseToTargetedElDist(); | ||
} | ||
switch (place) { | ||
case 'before': | ||
(_this$targetedNode2 = this.targetedNode) === null || _this$targetedNode2 === void 0 ? void 0 : (_this$targetedNode2$p = _this$targetedNode2.parentNode) === null || _this$targetedNode2$p === void 0 ? void 0 : _this$targetedNode2$p.insertBefore(this.draggedNode, this.targetedNode); | ||
break; | ||
getDropLocation() { | ||
if (this.canBeDropped()) { | ||
if (this.targetedNode.nodeName === 'LI' && !this.cursorIsIndentedEnough()) return 'before' | ||
else if (this.targetedNode instanceof this.listInterface) return 'inside' | ||
case 'inside': | ||
(_this$targetedNode3 = this.targetedNode) === null || _this$targetedNode3 === void 0 ? void 0 : _this$targetedNode3.appendChild(this.draggedNode); | ||
break; | ||
} | ||
} | ||
} | ||
}, { | ||
key: "calcMouseCoords", | ||
value: function calcMouseCoords(e) { | ||
// we're having the client coords because on the next lines, we use getBoundingClientRect which behaves in the same way | ||
this.cursor = { | ||
X: e.clientX, | ||
Y: e.clientY | ||
}; | ||
} | ||
}, { | ||
key: "calcMouseToTargetedElDist", | ||
value: function calcMouseToTargetedElDist() { | ||
if (!this.targetedNode) { | ||
return; | ||
} | ||
maybeDrop(e) { | ||
const location = this.getDropLocation(); | ||
if (location) this.dropTheItem(location, e); | ||
} | ||
dropTheItem(place) { | ||
switch (place) { | ||
case 'before': | ||
this.targetedNode.parentNode.insertBefore(this.draggedNode, this.targetedNode); | ||
break | ||
case 'inside': | ||
this.targetedNode.appendChild(this.draggedNode); | ||
break | ||
var offset = this.targetedNode.getBoundingClientRect(); | ||
this.targetNode = { | ||
X: offset.left, | ||
Y: offset.top | ||
}; | ||
var result = this.targetNode.Y - this.cursor.Y; | ||
var targetedElTopAbs = Math.abs(result); | ||
this.distances.mouseTo = { | ||
targetedElTop: result, | ||
targetedElTopAbs: targetedElTopAbs, | ||
targetedElBot: targetedElTopAbs - this.targetedNode.clientHeight | ||
}; | ||
} | ||
} | ||
}, { | ||
key: "areNested", | ||
value: function areNested(child, parent) { | ||
return !!child && !!parent && Array.from(parent === null || parent === void 0 ? void 0 : parent.querySelectorAll('li')).some(function (li) { | ||
return li === child; | ||
}); | ||
} | ||
}, { | ||
key: "cursorIsIndentedEnough", | ||
value: function cursorIsIndentedEnough() { | ||
return this.cursor.X - this.targetNode.X > 50; | ||
} | ||
}, { | ||
key: "mouseIsTooCloseToTop", | ||
value: function mouseIsTooCloseToTop() { | ||
var _this$distances; | ||
calcMouseCoords(e) { | ||
// we're having the client coords because on the next lines, we use getBoundingClientRect which behaves in the same way | ||
this.cursor.X = e.clientX; | ||
this.cursor.Y = e.clientY; | ||
} | ||
calcMouseToTargetedElDist() { | ||
if (!this.targetedNode) { | ||
return | ||
if (!((_this$distances = this.distances) !== null && _this$distances !== void 0 && _this$distances.droppingEdge)) return false; | ||
return this.cursor.Y - this.targetNode.Y < this.distances.droppingEdge; | ||
} | ||
}, { | ||
key: "managePlaceholderLists", | ||
value: function managePlaceholderLists() { | ||
var _this3 = this; | ||
let offset = this.targetedNode.getBoundingClientRect(); | ||
this.targetNode.X = offset.left; | ||
this.targetNode.Y = offset.top; | ||
var actions = this.analysePlaceHolderSituation(); | ||
actions.forEach(function (action) { | ||
switch (action) { | ||
case 'add': | ||
_this3.cleanupPlaceholderLists(); | ||
let result = this.targetNode.Y - this.cursor.Y; | ||
this.distances.mouseTo.targetedElTop = result; | ||
this.distances.mouseTo.targetedElTopAbs = Math.abs(result); | ||
this.dimensions.targetedEl.H = this.targetedNode.clientHeight; | ||
this.distances.mouseTo.targetedElBot = this.distances.mouseTo.targetedElTopAbs - this.dimensions.targetedEl.H; | ||
} | ||
_this3.addPlaceholderList(); | ||
areNested(child, parent) { | ||
return parent && Array.from(parent.querySelectorAll('li')).some(li => li === child) | ||
} | ||
break; | ||
cursorIsIndentedEnough() { | ||
return this.cursor.X - this.targetNode.X > 50 | ||
} | ||
case 'cleanup': | ||
_this3.cleanupPlaceholderLists(); | ||
mouseIsTooCloseToTop() { | ||
return this.cursor.Y - this.targetNode.Y < this.distances.droppingEdge | ||
} | ||
break; | ||
} | ||
}); | ||
} | ||
}, { | ||
key: "targetedNodeIsPlaceholder", | ||
value: function targetedNodeIsPlaceholder() { | ||
return this.targetedNode instanceof this.listInterface && this.targetedNode.classList.contains(this.classNames.placeholder); | ||
} | ||
}, { | ||
key: "getTargetedNodeDepth", | ||
value: function getTargetedNodeDepth() { | ||
var depth = 0; | ||
var el = this.targetedNode; | ||
var list = this.getSortableList(); | ||
managePlaceholderLists(e) { | ||
while (list !== ((_el = el) === null || _el === void 0 ? void 0 : _el.parentElement)) { | ||
var _el, _el2, _el3; | ||
let actions = this.analysePlaceHolderSituation(e); | ||
if (((_el2 = el) === null || _el2 === void 0 ? void 0 : _el2.parentElement) instanceof this.listInterface) depth++; | ||
el = (_el3 = el) === null || _el3 === void 0 ? void 0 : _el3.parentElement; | ||
} | ||
actions.forEach(action => { | ||
switch (action) { | ||
case 'add': | ||
this.cleanupPlaceholderLists(); | ||
this.addPlaceholderList(); | ||
break | ||
case 'cleanup': | ||
this.cleanupPlaceholderLists(); | ||
break | ||
return depth; | ||
} | ||
}, { | ||
key: "nestingThresholdReached", | ||
value: function nestingThresholdReached() { | ||
if (this.nestingLevels < 0) return false; | ||
if (this.nestingLevels === 0) return true; | ||
return this.getTargetedNodeDepth() >= this.nestingLevels; | ||
} | ||
}, { | ||
key: "analysePlaceHolderSituation", | ||
value: function analysePlaceHolderSituation() { | ||
if (!this.targetedNode || this.areNested(this.targetedNode, this.draggedNode)) { | ||
return []; | ||
} | ||
}); | ||
} | ||
targetedNodeIsPlaceholder() { | ||
return this.targetedNode instanceof this.listInterface | ||
&& this.targetedNode.classList.contains(this.classNames.placeholder) | ||
} | ||
var actions = []; | ||
getTargetedNodeDepth() { | ||
let depth = 0; | ||
let el = this.targetedNode; | ||
const list = this.getSortableList(); | ||
if (!this.cursorIsIndentedEnough() || this.mouseIsTooCloseToTop()) { | ||
if (!this.targetedNodeIsPlaceholder()) { | ||
actions.push('cleanup'); | ||
} | ||
} else if (this.targetedNode !== this.draggedNode && this.targetedNode.nodeName === 'LI' && !this.targetedNode.querySelectorAll(this.getListTagName()).length && !this.nestingThresholdReached()) { | ||
actions.push('add'); | ||
} | ||
while (list !== el.parentElement) { | ||
if (el.parentElement instanceof this.listInterface) depth++; | ||
el = el.parentElement; | ||
return actions; | ||
} | ||
}, { | ||
key: "animatePlaceholderList", | ||
value: function animatePlaceholderList() { | ||
var _this$draggedNode; | ||
return depth | ||
} | ||
this.placeholderInUse.style.minHeight = '0'; | ||
this.placeholderInUse.style.transition = 'min-height ease .2s'; | ||
this.placeholderInUse.style.minHeight = "".concat((_this$draggedNode = this.draggedNode) === null || _this$draggedNode === void 0 ? void 0 : _this$draggedNode.offsetHeight, "px"); | ||
} | ||
}, { | ||
key: "addPlaceholderList", | ||
value: function addPlaceholderList() { | ||
var _this$targetedNode4; | ||
nestingThresholdReached() { | ||
if (this.nestingLevels < 0) return false | ||
if (this.nestingLevels === 0) return true | ||
this.getPlaceholderList(); | ||
(_this$targetedNode4 = this.targetedNode) === null || _this$targetedNode4 === void 0 ? void 0 : _this$targetedNode4.appendChild(this.placeholderInUse); | ||
this.animatePlaceholderList(); | ||
} | ||
}, { | ||
key: "targetNodeIsIdentified", | ||
value: function targetNodeIsIdentified() { | ||
return !!this.targetedNode; | ||
} | ||
}, { | ||
key: "targetNodeIsBeingDragged", | ||
value: function targetNodeIsBeingDragged() { | ||
return this.targetNodeIsIdentified() && this.targetedNode === this.draggedNode; | ||
} | ||
}, { | ||
key: "targetNodeIsListWithItems", | ||
value: function targetNodeIsListWithItems() { | ||
return this.targetNodeIsIdentified() && this.targetedNode instanceof this.listInterface && !!this.targetedNode.querySelectorAll('li').length; | ||
} | ||
}, { | ||
key: "canBeDropped", | ||
value: function canBeDropped() { | ||
return this.targetNodeIsIdentified() && !this.targetNodeIsBeingDragged() && !this.targetNodeIsListWithItems() && !this.areNested(this.targetedNode, this.draggedNode); | ||
} | ||
}, { | ||
key: "cleanupPlaceholderLists", | ||
value: function cleanupPlaceholderLists() { | ||
var _this$getSortableList2, | ||
_this4 = this; | ||
return this.getTargetedNodeDepth() >= this.nestingLevels | ||
} | ||
analysePlaceHolderSituation() { | ||
if (!this.targetedNode || this.areNested(this.targetedNode, this.draggedNode)) { | ||
return [] | ||
var tag = this.getListTagName(); | ||
var listsArray = ((_this$getSortableList2 = this.getSortableList()) === null || _this$getSortableList2 === void 0 ? void 0 : _this$getSortableList2.querySelectorAll(tag)) || []; | ||
Array.from(listsArray).forEach(function (ul) { | ||
if (!ul.querySelectorAll('li').length) { | ||
ul.remove(); | ||
} else if (ul.classList.contains(_this4.classNames.placeholder)) { | ||
ul.classList.remove(_this4.classNames.placeholder); | ||
ul.style.minHeight = 'auto'; | ||
ul.dataset.id = ul.parentNode.dataset.id; | ||
} | ||
}); | ||
} | ||
}, { | ||
key: "initPlaceholderList", | ||
value: function initPlaceholderList() { | ||
var _this$placeholderList; | ||
let actions = []; | ||
this.placeholderList = document.createElement(this.getListTagName()); | ||
if (!this.cursorIsIndentedEnough() || this.mouseIsTooCloseToTop()) { | ||
if (!this.targetedNodeIsPlaceholder()) { | ||
actions.push('cleanup'); | ||
} | ||
} else if (this.targetedNode !== this.draggedNode | ||
&& this.targetedNode.nodeName === 'LI' | ||
&& !this.targetedNode.querySelectorAll(this.getListTagName()).length | ||
&& !this.nestingThresholdReached()) { | ||
actions.push('add'); | ||
(_this$placeholderList = this.placeholderList.classList).add.apply(_this$placeholderList, [this.classNames.placeholder].concat(_toConsumableArray(this.listClassNames))); | ||
} | ||
}, { | ||
key: "getPlaceholderList", | ||
value: function getPlaceholderList() { | ||
this.placeholderInUse = this.placeholderList.cloneNode(true); | ||
return this.placeholderInUse; | ||
} | ||
}]); | ||
return actions | ||
} | ||
return NestedSort; | ||
}(); | ||
animatePlaceholderList() { | ||
this.placeholderInUse.style.minHeight = '0'; | ||
this.placeholderInUse.style.transition = 'min-height ease .2s'; | ||
this.placeholderInUse.style.minHeight = `${this.draggedNode.offsetHeight}px`; | ||
} | ||
addPlaceholderList() { | ||
this.getPlaceholderList(); | ||
this.targetedNode.appendChild(this.placeholderInUse); | ||
this.animatePlaceholderList(); | ||
} | ||
targetNodeIsIdentified() { | ||
return !!this.targetedNode | ||
} | ||
targetNodeIsBeingDragged() { | ||
return this.targetNodeIsIdentified() | ||
&& this.targetedNode === this.draggedNode | ||
} | ||
targetNodeIsListWithItems() { | ||
return this.targetNodeIsIdentified() | ||
&& this.targetedNode instanceof this.listInterface | ||
&& this.targetedNode.querySelectorAll('li').length | ||
} | ||
canBeDropped() { | ||
return this.targetNodeIsIdentified() | ||
&& !this.targetNodeIsBeingDragged() | ||
&& !this.targetNodeIsListWithItems() | ||
&& !this.areNested(this.targetedNode, this.draggedNode) | ||
} | ||
cleanupPlaceholderLists() { | ||
this.getSortableList().querySelectorAll(this.getListTagName()).forEach(ul => { | ||
if (!ul.querySelectorAll('li').length) { | ||
ul.remove(); | ||
} else if (ul.classList.contains(this.classNames.placeholder)) { | ||
ul.classList.remove(this.classNames.placeholder); | ||
ul.style.minHeight = 'auto'; | ||
ul.dataset.id = ul.parentNode.dataset.id; | ||
} | ||
}); | ||
} | ||
initPlaceholderList() { | ||
this.placeholderList = document.createElement(this.getListTagName()); | ||
this.placeholderList.classList.add(this.classNames.placeholder, ...this.listClassNames); | ||
} | ||
getPlaceholderList() { | ||
this.placeholderInUse = this.placeholderList.cloneNode(true); | ||
return this.placeholderInUse | ||
} | ||
} | ||
export default NestedSort; |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global = global || self, global.NestedSort = factory()); | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.NestedSort = factory()); | ||
}(this, (function () { 'use strict'; | ||
function _arrayLikeToArray(arr, len) { | ||
if (len == null || len > arr.length) len = arr.length; | ||
for (var i = 0, arr2 = new Array(len); i < len; i++) { | ||
arr2[i] = arr[i]; | ||
} | ||
return arr2; | ||
} | ||
var arrayLikeToArray = _arrayLikeToArray; | ||
function _arrayWithoutHoles(arr) { | ||
if (Array.isArray(arr)) return arrayLikeToArray(arr); | ||
} | ||
var arrayWithoutHoles = _arrayWithoutHoles; | ||
function _iterableToArray(iter) { | ||
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); | ||
} | ||
var iterableToArray = _iterableToArray; | ||
function _unsupportedIterableToArray(o, minLen) { | ||
if (!o) return; | ||
if (typeof o === "string") return arrayLikeToArray(o, minLen); | ||
var n = Object.prototype.toString.call(o).slice(8, -1); | ||
if (n === "Object" && o.constructor) n = o.constructor.name; | ||
if (n === "Map" || n === "Set") return Array.from(n); | ||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen); | ||
} | ||
var unsupportedIterableToArray = _unsupportedIterableToArray; | ||
function _nonIterableSpread() { | ||
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); | ||
} | ||
var nonIterableSpread = _nonIterableSpread; | ||
function _toConsumableArray(arr) { | ||
return arrayWithoutHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableSpread(); | ||
} | ||
var toConsumableArray = _toConsumableArray; | ||
function _classCallCheck(instance, Constructor) { | ||
@@ -60,4 +13,2 @@ if (!(instance instanceof Constructor)) { | ||
var classCallCheck = _classCallCheck; | ||
function _defineProperties(target, props) { | ||
@@ -79,4 +30,2 @@ for (var i = 0; i < props.length; i++) { | ||
var createClass = _createClass; | ||
function _defineProperty(obj, key, value) { | ||
@@ -97,9 +46,38 @@ if (key in obj) { | ||
var defineProperty = _defineProperty; | ||
function _toConsumableArray(arr) { | ||
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); | ||
} | ||
function _arrayWithoutHoles(arr) { | ||
if (Array.isArray(arr)) return _arrayLikeToArray(arr); | ||
} | ||
function _iterableToArray(iter) { | ||
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); | ||
} | ||
function _unsupportedIterableToArray(o, minLen) { | ||
if (!o) return; | ||
if (typeof o === "string") return _arrayLikeToArray(o, minLen); | ||
var n = Object.prototype.toString.call(o).slice(8, -1); | ||
if (n === "Object" && o.constructor) n = o.constructor.name; | ||
if (n === "Map" || n === "Set") return Array.from(o); | ||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); | ||
} | ||
function _arrayLikeToArray(arr, len) { | ||
if (len == null || len > arr.length) len = arr.length; | ||
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; | ||
return arr2; | ||
} | ||
function _nonIterableSpread() { | ||
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); | ||
} | ||
var DataEngine = /*#__PURE__*/function () { | ||
/** | ||
* @constructor | ||
* @param {object[]} [data] | ||
* @param {object} [propertyMap={}] | ||
*/ | ||
@@ -111,4 +89,12 @@ function DataEngine(_ref) { | ||
classCallCheck(this, DataEngine); | ||
_classCallCheck(this, DataEngine); | ||
_defineProperty(this, "data", void 0); | ||
_defineProperty(this, "sortedData", void 0); | ||
_defineProperty(this, "sortedDataDomArray", void 0); | ||
_defineProperty(this, "propertyMap", void 0); | ||
this.data = data; | ||
@@ -121,3 +107,3 @@ this.sortedData = []; | ||
createClass(DataEngine, [{ | ||
_createClass(DataEngine, [{ | ||
key: "maybeTransformData", | ||
@@ -135,7 +121,2 @@ value: function maybeTransformData() { | ||
} | ||
/** | ||
* @param {PropertyKey} prop | ||
* @returns {PropertyKey} | ||
*/ | ||
}, { | ||
@@ -155,6 +136,2 @@ key: "getItemPropProxyName", | ||
} | ||
/** | ||
* @returns {object[]} | ||
*/ | ||
}, { | ||
@@ -165,3 +142,3 @@ key: "sortListItems", | ||
var items = toConsumableArray(this.data); | ||
var items = _toConsumableArray(this.data); | ||
@@ -189,11 +166,5 @@ var topLevelItems = items.filter(function (a) { | ||
}); | ||
this.sortedData = [].concat(toConsumableArray(topLevelItems), toConsumableArray(Object.values(childItems).flat())); | ||
this.sortedData = [].concat(_toConsumableArray(topLevelItems), _toConsumableArray(Object.values(childItems).flat())); | ||
return this.sortedData; | ||
} | ||
/** | ||
* @param {object[]} item | ||
* @param {string} nodeName | ||
* @returns {HTMLElement} | ||
*/ | ||
}, { | ||
@@ -207,11 +178,5 @@ key: "createItemElement", | ||
el.dataset.id = id; | ||
if (nodeName === 'li') el.innerHTML = text; | ||
if (nodeName === 'li' && text) el.innerHTML = text; | ||
return el; | ||
} | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
}, { | ||
@@ -222,9 +187,2 @@ key: "elementIsParentOfItem", | ||
} | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @param {string} nodeName | ||
* @returns {Element|null} | ||
*/ | ||
}, { | ||
@@ -235,8 +193,2 @@ key: "getParentNodeOfItem", | ||
} | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
}, { | ||
@@ -247,8 +199,2 @@ key: "elementIsAncestorOfItem", | ||
} | ||
/** | ||
* @param {HTMLElement} node | ||
* @param {object} item | ||
* @returns {HTMLElement} | ||
*/ | ||
}, { | ||
@@ -259,7 +205,2 @@ key: "getDirectListParentOfItem", | ||
} | ||
/** | ||
* @param {object} item | ||
* @returns {boolean} | ||
*/ | ||
}, { | ||
@@ -290,6 +231,2 @@ key: "maybeAppendItemToParentDom", | ||
} | ||
/** | ||
* @returns {array} | ||
*/ | ||
}, { | ||
@@ -305,3 +242,3 @@ key: "getListItemsDom", | ||
processedItems = this.sortedData.reduce(function (processedItems, item) { | ||
var id = item.id; | ||
var id = item.id.toString(); | ||
if (processedItems.includes(id)) return processedItems; | ||
@@ -327,7 +264,2 @@ var itemAdded; | ||
} | ||
/** | ||
* @param {HTMLOListElement|HTMLUListElement} list | ||
* @returns {object[]} | ||
*/ | ||
}, { | ||
@@ -338,3 +270,3 @@ key: "convertDomToData", | ||
return Array.from(list.querySelectorAll('li')).map(function (li) { | ||
return Array.from((list === null || list === void 0 ? void 0 : list.querySelectorAll('li')) || []).map(function (li) { | ||
var _ref2; | ||
@@ -347,9 +279,5 @@ | ||
}) + 1; | ||
return _ref2 = {}, defineProperty(_ref2, _this4.getItemPropProxyName('id'), li.dataset.id), defineProperty(_ref2, _this4.getItemPropProxyName('parent'), parent), defineProperty(_ref2, _this4.getItemPropProxyName('order'), order), _ref2; | ||
return _ref2 = {}, _defineProperty(_ref2, _this4.getItemPropProxyName('id'), li.dataset.id), _defineProperty(_ref2, _this4.getItemPropProxyName('parent'), parent), _defineProperty(_ref2, _this4.getItemPropProxyName('order'), order), _ref2; | ||
}); | ||
} | ||
/** | ||
* @returns {HTMLOListElement} | ||
*/ | ||
}, { | ||
@@ -370,18 +298,5 @@ key: "render", | ||
var NestedSort = /*#__PURE__*/function () { | ||
/** | ||
* @constructor | ||
* @param {object} [actions={}] | ||
* @param {array} [data] | ||
* @param {number} [droppingEdge=15] | ||
* @param {string|HTMLElement} el | ||
* @param {boolean} [init=true] | ||
* @param {array|string} [listClassNames] | ||
* @param {array|string} [listItemClassNames] | ||
* @param {number|string} [nestingLevels] | ||
* @param {object} [propertyMap={}] | ||
*/ | ||
function NestedSort(_ref) { | ||
var _ref$actions = _ref.actions; | ||
_ref$actions = _ref$actions === void 0 ? {} : _ref$actions; | ||
var onDrop = _ref$actions.onDrop, | ||
var _ref$actions = _ref.actions, | ||
actions = _ref$actions === void 0 ? {} : _ref$actions, | ||
data = _ref.data, | ||
@@ -399,11 +314,51 @@ _ref$droppingEdge = _ref.droppingEdge, | ||
classCallCheck(this, NestedSort); | ||
_classCallCheck(this, NestedSort); | ||
_defineProperty(this, "actions", void 0); | ||
_defineProperty(this, "classNames", void 0); | ||
_defineProperty(this, "cursor", void 0); | ||
_defineProperty(this, "data", void 0); | ||
_defineProperty(this, "dataEngine", void 0); | ||
_defineProperty(this, "distances", void 0); | ||
_defineProperty(this, "draggedNode", void 0); | ||
_defineProperty(this, "initialised", void 0); | ||
_defineProperty(this, "listClassNames", void 0); | ||
_defineProperty(this, "listEventListeners", void 0); | ||
_defineProperty(this, "listInterface", void 0); | ||
_defineProperty(this, "listItemClassNames", void 0); | ||
_defineProperty(this, "mainListClassName", void 0); | ||
_defineProperty(this, "nestingLevels", void 0); | ||
_defineProperty(this, "placeholderList", void 0); | ||
_defineProperty(this, "placeholderInUse", void 0); | ||
_defineProperty(this, "propertyMap", void 0); | ||
_defineProperty(this, "sortableList", void 0); | ||
_defineProperty(this, "targetedNode", void 0); | ||
_defineProperty(this, "targetNode", void 0); | ||
_defineProperty(this, "wrapper", void 0); | ||
var element = typeof el === 'string' ? document.querySelector(el) : el; | ||
var elementIsAList = element instanceof HTMLOListElement || element instanceof HTMLUListElement; | ||
this.wrapper = elementIsAList ? undefined : element; | ||
this.sortableList = elementIsAList ? element : null; | ||
this.data = data; | ||
this.selector = el; | ||
this.sortableList = null; | ||
this.placeholderList = null; | ||
this.placeholderInUse = null; | ||
this.draggedNode = null; | ||
this.targetedNode = null; | ||
this.listClassNames = this.createListClassNamesArray(listClassNames); | ||
@@ -414,25 +369,8 @@ this.mainListClassName = this.listClassNames[0] || 'nested-sort'; | ||
this.actions = { | ||
onDrop: onDrop | ||
onDrop: actions.onDrop | ||
}; | ||
this.initialised = false; | ||
this.targetNode = { | ||
X: null, | ||
Y: null | ||
}; | ||
this.distances = { | ||
droppingEdge: droppingEdge, | ||
droppingEdgeNegative: droppingEdge * -1, | ||
mouseTo: { | ||
targetedElTop: undefined | ||
} | ||
droppingEdge: droppingEdge | ||
}; | ||
this.dimensions = { | ||
targetedEl: { | ||
H: undefined | ||
} | ||
}; | ||
this.cursor = { | ||
X: null, | ||
Y: null | ||
}; | ||
this.classNames = { | ||
@@ -459,8 +397,7 @@ dragged: 'ns-dragged', | ||
createClass(NestedSort, [{ | ||
_createClass(NestedSort, [{ | ||
key: "getListInterface", | ||
value: function getListInterface() { | ||
if (Array.isArray(this.data) && this.data.length) return HTMLOListElement; | ||
var el = this.selector instanceof HTMLElement ? this.selector : document.querySelector(this.selector); | ||
return el instanceof HTMLOListElement ? HTMLOListElement : HTMLUListElement; | ||
return this.sortableList instanceof HTMLOListElement ? HTMLOListElement : HTMLUListElement; | ||
} | ||
@@ -470,6 +407,3 @@ }, { | ||
value: function getDataEngine() { | ||
if (this.dataEngine instanceof DataEngine) { | ||
return this.dataEngine; | ||
} | ||
if (this.dataEngine) return this.dataEngine; | ||
this.dataEngine = new DataEngine({ | ||
@@ -490,7 +424,6 @@ data: this.data, | ||
value: function maybeInitDataDom() { | ||
if (!(Array.isArray(this.data) && this.data.length)) return; | ||
var wrapper = document.querySelector(this.selector); | ||
if (!(Array.isArray(this.data) && this.data.length && this.wrapper)) return; | ||
var list = this.getDataEngine().render(); | ||
wrapper.innerHTML = ''; | ||
wrapper.appendChild(list); | ||
this.wrapper.innerHTML = ''; | ||
this.wrapper.appendChild(list); | ||
} | ||
@@ -505,11 +438,6 @@ }, { | ||
value: function getSortableList() { | ||
var _this$wrapper; | ||
if (this.sortableList instanceof this.listInterface) return this.sortableList; | ||
if (this.selector instanceof this.listInterface) { | ||
this.sortableList = this.selector; | ||
} else { | ||
var list = document.querySelector(this.selector); | ||
this.sortableList = list instanceof this.listInterface ? list : list.querySelector(this.getListTagName()); | ||
} | ||
this.sortableList = (_this$wrapper = this.wrapper) === null || _this$wrapper === void 0 ? void 0 : _this$wrapper.querySelector(this.getListTagName()); | ||
return this.sortableList; | ||
@@ -524,4 +452,5 @@ } | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
(_list$classList = list.classList).add.apply(_list$classList, toConsumableArray(this.listClassNames.concat(this.mainListClassName))); | ||
(_list$classList = list.classList).add.apply(_list$classList, _toConsumableArray(this.listClassNames.concat(this.mainListClassName))); | ||
@@ -531,3 +460,3 @@ list.querySelectorAll(this.getListTagName()).forEach(function (l) { | ||
(_l$classList = l.classList).add.apply(_l$classList, toConsumableArray(_this.listClassNames)); | ||
(_l$classList = l.classList).add.apply(_l$classList, _toConsumableArray(_this.listClassNames)); | ||
}); | ||
@@ -537,3 +466,3 @@ list.querySelectorAll('li').forEach(function (li) { | ||
(_li$classList = li.classList).add.apply(_li$classList, toConsumableArray(_this.listItemClassNames)); | ||
(_li$classList = li.classList).add.apply(_li$classList, _toConsumableArray(_this.listItemClassNames)); | ||
}); | ||
@@ -545,5 +474,6 @@ } | ||
var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
var className = "".concat(this.mainListClassName, "--enabled"); | ||
var classList = this.getSortableList().classList; | ||
return enabled ? classList.add(className) : classList.remove(className); | ||
enabled ? list.classList.add(className) : list.classList.remove(className); | ||
} | ||
@@ -553,5 +483,7 @@ }, { | ||
value: function toggleListItemAttributes() { | ||
var _this$getSortableList; | ||
var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
this.getSortableList().querySelectorAll('li').forEach(function (el) { | ||
el.setAttribute('draggable', enable); | ||
(_this$getSortableList = this.getSortableList()) === null || _this$getSortableList === void 0 ? void 0 : _this$getSortableList.querySelectorAll('li').forEach(function (el) { | ||
el.setAttribute('draggable', enable.toString()); | ||
}); | ||
@@ -566,8 +498,5 @@ } | ||
var list = this.getSortableList(); | ||
if (!list) return; | ||
Object.keys(this.listEventListeners).forEach(function (event) { | ||
if (remove) { | ||
list.removeEventListener(event, _this2.listEventListeners[event]); | ||
} else { | ||
list.addEventListener(event, _this2.listEventListeners[event], false); | ||
} | ||
remove ? list.removeEventListener(event, _this2.listEventListeners[event]) : list.addEventListener(event, _this2.listEventListeners[event], false); | ||
}); | ||
@@ -600,3 +529,3 @@ } | ||
key: "removeClassFromEl", | ||
value: function removeClassFromEl(el, className) { | ||
value: function removeClassFromEl(className, el) { | ||
if (el && el.classList.contains(className)) { | ||
@@ -615,5 +544,7 @@ el.classList.remove(className); | ||
value: function onDragStart(e) { | ||
var _e$dataTransfer; | ||
this.draggedNode = e.target; | ||
this.draggedNode.classList.add(this.classNames.dragged); | ||
e.dataTransfer.setData('text', 'Drag started!'); // Hack for Firefox! | ||
(_e$dataTransfer = e.dataTransfer) === null || _e$dataTransfer === void 0 ? void 0 : _e$dataTransfer.setData('text', 'Drag started!'); // Hack for Firefox! | ||
} | ||
@@ -626,3 +557,3 @@ }, { | ||
this.updateCoordination(e); | ||
this.managePlaceholderLists(e); | ||
this.managePlaceholderLists(); | ||
} | ||
@@ -633,3 +564,3 @@ }, { | ||
if (!this.canBeTargeted(e.target)) return; | ||
this.removeClassFromEl(this.targetedNode, this.classNames.targeted); | ||
this.removeClassFromEl(this.classNames.targeted, this.targetedNode); | ||
this.targetedNode = e.target; | ||
@@ -642,7 +573,7 @@ this.targetedNode.classList.add(this.classNames.targeted); | ||
e.stopPropagation(); | ||
this.removeClassFromEl(this.draggedNode, this.classNames.dragged); | ||
this.removeClassFromEl(this.targetedNode, this.classNames.targeted); | ||
this.removeClassFromEl(this.classNames.dragged, this.draggedNode); | ||
this.removeClassFromEl(this.classNames.targeted, this.targetedNode); | ||
this.cleanupPlaceholderLists(); | ||
this.draggedNode = null; | ||
this.targetedNode = null; | ||
delete this.draggedNode; | ||
delete this.targetedNode; | ||
} | ||
@@ -670,3 +601,5 @@ }, { | ||
if (this.canBeDropped()) { | ||
if (this.targetedNode.nodeName === 'LI' && !this.cursorIsIndentedEnough()) return 'before';else if (this.targetedNode instanceof this.listInterface) return 'inside'; | ||
var _this$targetedNode; | ||
if (((_this$targetedNode = this.targetedNode) === null || _this$targetedNode === void 0 ? void 0 : _this$targetedNode.nodeName) === 'LI') return 'before';else if (this.targetedNode instanceof this.listInterface) return 'inside'; | ||
} | ||
@@ -676,5 +609,5 @@ } | ||
key: "maybeDrop", | ||
value: function maybeDrop(e) { | ||
value: function maybeDrop() { | ||
var location = this.getDropLocation(); | ||
if (location) this.dropTheItem(location, e); | ||
if (location) this.dropTheItem(location); | ||
} | ||
@@ -684,9 +617,11 @@ }, { | ||
value: function dropTheItem(place) { | ||
var _this$targetedNode2, _this$targetedNode2$p, _this$targetedNode3; | ||
switch (place) { | ||
case 'before': | ||
this.targetedNode.parentNode.insertBefore(this.draggedNode, this.targetedNode); | ||
(_this$targetedNode2 = this.targetedNode) === null || _this$targetedNode2 === void 0 ? void 0 : (_this$targetedNode2$p = _this$targetedNode2.parentNode) === null || _this$targetedNode2$p === void 0 ? void 0 : _this$targetedNode2$p.insertBefore(this.draggedNode, this.targetedNode); | ||
break; | ||
case 'inside': | ||
this.targetedNode.appendChild(this.draggedNode); | ||
(_this$targetedNode3 = this.targetedNode) === null || _this$targetedNode3 === void 0 ? void 0 : _this$targetedNode3.appendChild(this.draggedNode); | ||
break; | ||
@@ -699,4 +634,6 @@ } | ||
// we're having the client coords because on the next lines, we use getBoundingClientRect which behaves in the same way | ||
this.cursor.X = e.clientX; | ||
this.cursor.Y = e.clientY; | ||
this.cursor = { | ||
X: e.clientX, | ||
Y: e.clientY | ||
}; | ||
} | ||
@@ -711,9 +648,13 @@ }, { | ||
var offset = this.targetedNode.getBoundingClientRect(); | ||
this.targetNode.X = offset.left; | ||
this.targetNode.Y = offset.top; | ||
this.targetNode = { | ||
X: offset.left, | ||
Y: offset.top | ||
}; | ||
var result = this.targetNode.Y - this.cursor.Y; | ||
this.distances.mouseTo.targetedElTop = result; | ||
this.distances.mouseTo.targetedElTopAbs = Math.abs(result); | ||
this.dimensions.targetedEl.H = this.targetedNode.clientHeight; | ||
this.distances.mouseTo.targetedElBot = this.distances.mouseTo.targetedElTopAbs - this.dimensions.targetedEl.H; | ||
var targetedElTopAbs = Math.abs(result); | ||
this.distances.mouseTo = { | ||
targetedElTop: result, | ||
targetedElTopAbs: targetedElTopAbs, | ||
targetedElBot: targetedElTopAbs - this.targetedNode.clientHeight | ||
}; | ||
} | ||
@@ -723,3 +664,3 @@ }, { | ||
value: function areNested(child, parent) { | ||
return parent && Array.from(parent.querySelectorAll('li')).some(function (li) { | ||
return !!child && !!parent && Array.from(parent === null || parent === void 0 ? void 0 : parent.querySelectorAll('li')).some(function (li) { | ||
return li === child; | ||
@@ -736,2 +677,5 @@ }); | ||
value: function mouseIsTooCloseToTop() { | ||
var _this$distances; | ||
if (!((_this$distances = this.distances) !== null && _this$distances !== void 0 && _this$distances.droppingEdge)) return false; | ||
return this.cursor.Y - this.targetNode.Y < this.distances.droppingEdge; | ||
@@ -741,6 +685,6 @@ } | ||
key: "managePlaceholderLists", | ||
value: function managePlaceholderLists(e) { | ||
value: function managePlaceholderLists() { | ||
var _this3 = this; | ||
var actions = this.analysePlaceHolderSituation(e); | ||
var actions = this.analysePlaceHolderSituation(); | ||
actions.forEach(function (action) { | ||
@@ -774,5 +718,7 @@ switch (action) { | ||
while (list !== el.parentElement) { | ||
if (el.parentElement instanceof this.listInterface) depth++; | ||
el = el.parentElement; | ||
while (list !== ((_el = el) === null || _el === void 0 ? void 0 : _el.parentElement)) { | ||
var _el, _el2, _el3; | ||
if (((_el2 = el) === null || _el2 === void 0 ? void 0 : _el2.parentElement) instanceof this.listInterface) depth++; | ||
el = (_el3 = el) === null || _el3 === void 0 ? void 0 : _el3.parentElement; | ||
} | ||
@@ -811,5 +757,7 @@ | ||
value: function animatePlaceholderList() { | ||
var _this$draggedNode; | ||
this.placeholderInUse.style.minHeight = '0'; | ||
this.placeholderInUse.style.transition = 'min-height ease .2s'; | ||
this.placeholderInUse.style.minHeight = "".concat(this.draggedNode.offsetHeight, "px"); | ||
this.placeholderInUse.style.minHeight = "".concat((_this$draggedNode = this.draggedNode) === null || _this$draggedNode === void 0 ? void 0 : _this$draggedNode.offsetHeight, "px"); | ||
} | ||
@@ -819,4 +767,6 @@ }, { | ||
value: function addPlaceholderList() { | ||
var _this$targetedNode4; | ||
this.getPlaceholderList(); | ||
this.targetedNode.appendChild(this.placeholderInUse); | ||
(_this$targetedNode4 = this.targetedNode) === null || _this$targetedNode4 === void 0 ? void 0 : _this$targetedNode4.appendChild(this.placeholderInUse); | ||
this.animatePlaceholderList(); | ||
@@ -837,3 +787,3 @@ } | ||
value: function targetNodeIsListWithItems() { | ||
return this.targetNodeIsIdentified() && this.targetedNode instanceof this.listInterface && this.targetedNode.querySelectorAll('li').length; | ||
return this.targetNodeIsIdentified() && this.targetedNode instanceof this.listInterface && !!this.targetedNode.querySelectorAll('li').length; | ||
} | ||
@@ -848,5 +798,8 @@ }, { | ||
value: function cleanupPlaceholderLists() { | ||
var _this4 = this; | ||
var _this$getSortableList2, | ||
_this4 = this; | ||
this.getSortableList().querySelectorAll(this.getListTagName()).forEach(function (ul) { | ||
var tag = this.getListTagName(); | ||
var listsArray = ((_this$getSortableList2 = this.getSortableList()) === null || _this$getSortableList2 === void 0 ? void 0 : _this$getSortableList2.querySelectorAll(tag)) || []; | ||
Array.from(listsArray).forEach(function (ul) { | ||
if (!ul.querySelectorAll('li').length) { | ||
@@ -868,3 +821,3 @@ ul.remove(); | ||
(_this$placeholderList = this.placeholderList.classList).add.apply(_this$placeholderList, [this.classNames.placeholder].concat(toConsumableArray(this.listClassNames))); | ||
(_this$placeholderList = this.placeholderList.classList).add.apply(_this$placeholderList, [this.classNames.placeholder].concat(_toConsumableArray(this.listClassNames))); | ||
} | ||
@@ -871,0 +824,0 @@ }, { |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).NestedSort=t()}(this,(function(){"use strict";var e=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var s=0,i=new Array(t);s<t;s++)i[s]=e[s];return i};var t=function(t){if(Array.isArray(t))return e(t)};var s=function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)};var i=function(t,s){if(t){if("string"==typeof t)return e(t,s);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(i):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?e(t,s):void 0}};var a=function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")};var r=function(e){return t(e)||s(e)||i(e)||a()};var n=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")};function o(e,t){for(var s=0;s<t.length;s++){var i=t[s];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}var l=function(e,t,s){return t&&o(e.prototype,t),s&&o(e,s),e};var d=function(e,t,s){return t in e?Object.defineProperty(e,t,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[t]=s,e},h=function(){function e(t){var s=t.data,i=t.propertyMap,a=void 0===i?{}:i;n(this,e),this.data=s,this.sortedData=[],this.sortedDataDomArray=[],this.propertyMap=a,this.maybeTransformData()}return l(e,[{key:"maybeTransformData",value:function(){if(Object.keys(this.propertyMap).length&&Array.isArray(this.data)){var e=this.getItemPropProxyName.bind(this);this.data=this.data.map((function(t){return new Proxy(t,{get:function(t,s,i){return Reflect.get(t,e(s),i)}})}))}}},{key:"getItemPropProxyName",value:function(e){return Object.prototype.hasOwnProperty.call(this.propertyMap,e)?this.propertyMap[e]:e}},{key:"isTopLevelItem",value:function(e){return!e.parent}},{key:"sortListItems",value:function(){var e=this,t=r(this.data),s=t.filter((function(t){return e.isTopLevelItem(t)})).sort((function(e,t){return e.order&&t.order?e.order-t.order:0})),i=t.filter((function(t){return!e.isTopLevelItem(t)})).reduce((function(e,t){return Object.prototype.hasOwnProperty.call(e,t.parent)?e[t.parent].push(t):e[t.parent]=[t],e}),{});return Object.keys(i).forEach((function(e){i[e].sort((function(e,t){return e.order&&t.order?e.order-t.order:0}))})),this.sortedData=[].concat(r(s),r(Object.values(i).flat())),this.sortedData}},{key:"createItemElement",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"li",s=e.id,i=e.text,a=document.createElement(t);return a.dataset.id=s,"li"===t&&(a.innerHTML=i),a}},{key:"elementIsParentOfItem",value:function(e,t){return e.dataset.id==="".concat(t.parent)}},{key:"getParentNodeOfItem",value:function(e,t,s){return e.querySelector("".concat(s,'[data-id="').concat(t.parent,'"]'))}},{key:"elementIsAncestorOfItem",value:function(e,t){return!!this.getParentNodeOfItem(e,t,"li")}},{key:"getDirectListParentOfItem",value:function(e,t){return this.getParentNodeOfItem(e,t,"ol")}},{key:"maybeAppendItemToParentDom",value:function(e){var t=this,s=e.parent,i=this.sortedDataDomArray.find((function(s){return t.elementIsParentOfItem(s,e)||t.elementIsAncestorOfItem(s,e)}));if(!i)return!1;var a=this.createItemElement(e),r=this.getDirectListParentOfItem(i,e);r||(r=this.createItemElement({id:s},"ol"),(this.getParentNodeOfItem(i,e,"li")||i).appendChild(r));return r.appendChild(a),!0}},{key:"getListItemsDom",value:function(){var e=this;this.sortedDataDomArray=[];for(var t=[];t.length!==this.sortListItems().length;)t=this.sortedData.reduce((function(t,s){var i,a=s.id;if(t.includes(a))return t;if(s.parent)i=e.maybeAppendItemToParentDom(s);else{var r=e.createItemElement(s);e.sortedDataDomArray.push(r),i=!0}return i&&t.push(a),t}),t);return this.sortedDataDomArray}},{key:"convertDomToData",value:function(e){var t=this;return Array.from(e.querySelectorAll("li")).map((function(e){var s,i=e.parentNode,a=i.dataset.id,r=Array.from(i.children).findIndex((function(t){return t===e}))+1;return d(s={},t.getItemPropProxyName("id"),e.dataset.id),d(s,t.getItemPropProxyName("parent"),a),d(s,t.getItemPropProxyName("order"),r),s}))}},{key:"render",value:function(){var e=document.createElement("ol");return this.getListItemsDom().forEach((function(t){return e.appendChild(t)})),e}}]),e}();return function(){function e(t){var s=t.actions,i=(s=void 0===s?{}:s).onDrop,a=t.data,r=t.droppingEdge,o=void 0===r?15:r,l=t.el,d=t.init,h=void 0===d||d,c=t.listClassNames,u=t.listItemClassNames,g=t.nestingLevels,f=t.propertyMap,m=void 0===f?{}:f;n(this,e),this.data=a,this.selector=l,this.sortableList=null,this.placeholderList=null,this.placeholderInUse=null,this.draggedNode=null,this.targetedNode=null,this.listClassNames=this.createListClassNamesArray(c),this.mainListClassName=this.listClassNames[0]||"nested-sort",this.listItemClassNames=this.createListClassNamesArray(u),this.propertyMap=m,this.actions={onDrop:i},this.initialised=!1,this.targetNode={X:null,Y:null},this.distances={droppingEdge:o,droppingEdgeNegative:-1*o,mouseTo:{targetedElTop:void 0}},this.dimensions={targetedEl:{H:void 0}},this.cursor={X:null,Y:null},this.classNames={dragged:"ns-dragged",placeholder:"ns-placeholder",targeted:"ns-targeted"},this.listEventListeners={dragover:this.onDragOver.bind(this),dragstart:this.onDragStart.bind(this),dragenter:this.onDragEnter.bind(this),dragend:this.onDragEnd.bind(this),drop:this.onDrop.bind(this)};var p=parseInt(g);this.nestingLevels=isNaN(p)?-1:p,this.listInterface=this.getListInterface(),this.maybeInitDataDom(),this.addListAttributes(),h&&this.initDragAndDrop()}return l(e,[{key:"getListInterface",value:function(){return Array.isArray(this.data)&&this.data.length||(this.selector instanceof HTMLElement?this.selector:document.querySelector(this.selector))instanceof HTMLOListElement?HTMLOListElement:HTMLUListElement}},{key:"getDataEngine",value:function(){return this.dataEngine instanceof h||(this.dataEngine=new h({data:this.data,propertyMap:this.propertyMap})),this.dataEngine}},{key:"createListClassNamesArray",value:function(e){return e?Array.isArray(e)?e:e.split(" "):[]}},{key:"maybeInitDataDom",value:function(){if(Array.isArray(this.data)&&this.data.length){var e=document.querySelector(this.selector),t=this.getDataEngine().render();e.innerHTML="",e.appendChild(t)}}},{key:"getListTagName",value:function(){return this.listInterface===HTMLOListElement?"ol":"ul"}},{key:"getSortableList",value:function(){if(this.sortableList instanceof this.listInterface)return this.sortableList;if(this.selector instanceof this.listInterface)this.sortableList=this.selector;else{var e=document.querySelector(this.selector);this.sortableList=e instanceof this.listInterface?e:e.querySelector(this.getListTagName())}return this.sortableList}},{key:"addListAttributes",value:function(){var e,t=this,s=this.getSortableList();(e=s.classList).add.apply(e,r(this.listClassNames.concat(this.mainListClassName))),s.querySelectorAll(this.getListTagName()).forEach((function(e){var s;(s=e.classList).add.apply(s,r(t.listClassNames))})),s.querySelectorAll("li").forEach((function(e){var s;(s=e.classList).add.apply(s,r(t.listItemClassNames))}))}},{key:"toggleMainListLifeCycleClassName",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t="".concat(this.mainListClassName,"--enabled"),s=this.getSortableList().classList;return e?s.add(t):s.remove(t)}},{key:"toggleListItemAttributes",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.getSortableList().querySelectorAll("li").forEach((function(t){t.setAttribute("draggable",e)}))}},{key:"toggleListEventListeners",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],s=this.getSortableList();Object.keys(this.listEventListeners).forEach((function(i){t?s.removeEventListener(i,e.listEventListeners[i]):s.addEventListener(i,e.listEventListeners[i],!1)}))}},{key:"initDragAndDrop",value:function(){this.initialised||(this.toggleListEventListeners(),this.initPlaceholderList(),this.toggleListItemAttributes(),this.toggleMainListLifeCycleClassName(),this.initialised=!0)}},{key:"init",value:function(){this.initDragAndDrop()}},{key:"destroy",value:function(){this.toggleListEventListeners(!0),this.toggleListItemAttributes(!1),this.toggleMainListLifeCycleClassName(!1),this.initialised=!1}},{key:"removeClassFromEl",value:function(e,t){e&&e.classList.contains(t)&&e.classList.remove(t)}},{key:"canBeTargeted",value:function(e){return!(!this.draggedNode||this.draggedNode===e)&&("LI"===e.nodeName||e instanceof this.listInterface&&e.classList.contains(this.classNames.placeholder))}},{key:"onDragStart",value:function(e){this.draggedNode=e.target,this.draggedNode.classList.add(this.classNames.dragged),e.dataTransfer.setData("text","Drag started!")}},{key:"onDragOver",value:function(e){e.preventDefault(),this.updateCoordination(e),this.managePlaceholderLists(e)}},{key:"onDragEnter",value:function(e){this.canBeTargeted(e.target)&&(this.removeClassFromEl(this.targetedNode,this.classNames.targeted),this.targetedNode=e.target,this.targetedNode.classList.add(this.classNames.targeted))}},{key:"onDragEnd",value:function(e){e.stopPropagation(),this.removeClassFromEl(this.draggedNode,this.classNames.dragged),this.removeClassFromEl(this.targetedNode,this.classNames.targeted),this.cleanupPlaceholderLists(),this.draggedNode=null,this.targetedNode=null}},{key:"onDrop",value:function(e){e.stopPropagation(),this.maybeDrop(),this.cleanupPlaceholderLists(),"function"==typeof this.actions.onDrop&&this.actions.onDrop(this.getDataEngine().convertDomToData(this.getSortableList()))}},{key:"updateCoordination",value:function(e){this.calcMouseCoords(e),this.calcMouseToTargetedElDist()}},{key:"getDropLocation",value:function(){if(this.canBeDropped()){if("LI"===this.targetedNode.nodeName&&!this.cursorIsIndentedEnough())return"before";if(this.targetedNode instanceof this.listInterface)return"inside"}}},{key:"maybeDrop",value:function(e){var t=this.getDropLocation();t&&this.dropTheItem(t,e)}},{key:"dropTheItem",value:function(e){switch(e){case"before":this.targetedNode.parentNode.insertBefore(this.draggedNode,this.targetedNode);break;case"inside":this.targetedNode.appendChild(this.draggedNode)}}},{key:"calcMouseCoords",value:function(e){this.cursor.X=e.clientX,this.cursor.Y=e.clientY}},{key:"calcMouseToTargetedElDist",value:function(){if(this.targetedNode){var e=this.targetedNode.getBoundingClientRect();this.targetNode.X=e.left,this.targetNode.Y=e.top;var t=this.targetNode.Y-this.cursor.Y;this.distances.mouseTo.targetedElTop=t,this.distances.mouseTo.targetedElTopAbs=Math.abs(t),this.dimensions.targetedEl.H=this.targetedNode.clientHeight,this.distances.mouseTo.targetedElBot=this.distances.mouseTo.targetedElTopAbs-this.dimensions.targetedEl.H}}},{key:"areNested",value:function(e,t){return t&&Array.from(t.querySelectorAll("li")).some((function(t){return t===e}))}},{key:"cursorIsIndentedEnough",value:function(){return this.cursor.X-this.targetNode.X>50}},{key:"mouseIsTooCloseToTop",value:function(){return this.cursor.Y-this.targetNode.Y<this.distances.droppingEdge}},{key:"managePlaceholderLists",value:function(e){var t=this;this.analysePlaceHolderSituation(e).forEach((function(e){switch(e){case"add":t.cleanupPlaceholderLists(),t.addPlaceholderList();break;case"cleanup":t.cleanupPlaceholderLists()}}))}},{key:"targetedNodeIsPlaceholder",value:function(){return this.targetedNode instanceof this.listInterface&&this.targetedNode.classList.contains(this.classNames.placeholder)}},{key:"getTargetedNodeDepth",value:function(){for(var e=0,t=this.targetedNode,s=this.getSortableList();s!==t.parentElement;)t.parentElement instanceof this.listInterface&&e++,t=t.parentElement;return e}},{key:"nestingThresholdReached",value:function(){return!(this.nestingLevels<0)&&(0===this.nestingLevels||this.getTargetedNodeDepth()>=this.nestingLevels)}},{key:"analysePlaceHolderSituation",value:function(){if(!this.targetedNode||this.areNested(this.targetedNode,this.draggedNode))return[];var e=[];return!this.cursorIsIndentedEnough()||this.mouseIsTooCloseToTop()?this.targetedNodeIsPlaceholder()||e.push("cleanup"):this.targetedNode===this.draggedNode||"LI"!==this.targetedNode.nodeName||this.targetedNode.querySelectorAll(this.getListTagName()).length||this.nestingThresholdReached()||e.push("add"),e}},{key:"animatePlaceholderList",value:function(){this.placeholderInUse.style.minHeight="0",this.placeholderInUse.style.transition="min-height ease .2s",this.placeholderInUse.style.minHeight="".concat(this.draggedNode.offsetHeight,"px")}},{key:"addPlaceholderList",value:function(){this.getPlaceholderList(),this.targetedNode.appendChild(this.placeholderInUse),this.animatePlaceholderList()}},{key:"targetNodeIsIdentified",value:function(){return!!this.targetedNode}},{key:"targetNodeIsBeingDragged",value:function(){return this.targetNodeIsIdentified()&&this.targetedNode===this.draggedNode}},{key:"targetNodeIsListWithItems",value:function(){return this.targetNodeIsIdentified()&&this.targetedNode instanceof this.listInterface&&this.targetedNode.querySelectorAll("li").length}},{key:"canBeDropped",value:function(){return this.targetNodeIsIdentified()&&!this.targetNodeIsBeingDragged()&&!this.targetNodeIsListWithItems()&&!this.areNested(this.targetedNode,this.draggedNode)}},{key:"cleanupPlaceholderLists",value:function(){var e=this;this.getSortableList().querySelectorAll(this.getListTagName()).forEach((function(t){t.querySelectorAll("li").length?t.classList.contains(e.classNames.placeholder)&&(t.classList.remove(e.classNames.placeholder),t.style.minHeight="auto",t.dataset.id=t.parentNode.dataset.id):t.remove()}))}},{key:"initPlaceholderList",value:function(){var e;this.placeholderList=document.createElement(this.getListTagName()),(e=this.placeholderList.classList).add.apply(e,[this.classNames.placeholder].concat(r(this.listClassNames)))}},{key:"getPlaceholderList",value:function(){return this.placeholderInUse=this.placeholderList.cloneNode(!0),this.placeholderInUse}}]),e}()})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).NestedSort=t()}(this,(function(){"use strict";function e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function t(e,t){for(var i=0;i<t.length;i++){var s=t[i];s.enumerable=s.enumerable||!1,s.configurable=!0,"value"in s&&(s.writable=!0),Object.defineProperty(e,s.key,s)}}function i(e,i,s){return i&&t(e.prototype,i),s&&t(e,s),e}function s(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function a(e){return function(e){if(Array.isArray(e))return r(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var i=Object.prototype.toString.call(e).slice(8,-1);"Object"===i&&e.constructor&&(i=e.constructor.name);if("Map"===i||"Set"===i)return Array.from(e);if("Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i))return r(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var i=0,s=new Array(t);i<t;i++)s[i]=e[i];return s}var n=function(){function t(i){var a=i.data,r=i.propertyMap,n=void 0===r?{}:r;e(this,t),s(this,"data",void 0),s(this,"sortedData",void 0),s(this,"sortedDataDomArray",void 0),s(this,"propertyMap",void 0),this.data=a,this.sortedData=[],this.sortedDataDomArray=[],this.propertyMap=n,this.maybeTransformData()}return i(t,[{key:"maybeTransformData",value:function(){if(Object.keys(this.propertyMap).length&&Array.isArray(this.data)){var e=this.getItemPropProxyName.bind(this);this.data=this.data.map((function(t){return new Proxy(t,{get:function(t,i,s){return Reflect.get(t,e(i),s)}})}))}}},{key:"getItemPropProxyName",value:function(e){return Object.prototype.hasOwnProperty.call(this.propertyMap,e)?this.propertyMap[e]:e}},{key:"isTopLevelItem",value:function(e){return!e.parent}},{key:"sortListItems",value:function(){var e=this,t=a(this.data),i=t.filter((function(t){return e.isTopLevelItem(t)})).sort((function(e,t){return e.order&&t.order?e.order-t.order:0})),s=t.filter((function(t){return!e.isTopLevelItem(t)})).reduce((function(e,t){return Object.prototype.hasOwnProperty.call(e,t.parent)?e[t.parent].push(t):e[t.parent]=[t],e}),{});return Object.keys(s).forEach((function(e){s[e].sort((function(e,t){return e.order&&t.order?e.order-t.order:0}))})),this.sortedData=[].concat(a(i),a(Object.values(s).flat())),this.sortedData}},{key:"createItemElement",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"li",i=e.id,s=e.text,a=document.createElement(t);return a.dataset.id=i,"li"===t&&s&&(a.innerHTML=s),a}},{key:"elementIsParentOfItem",value:function(e,t){return e.dataset.id==="".concat(t.parent)}},{key:"getParentNodeOfItem",value:function(e,t,i){return e.querySelector("".concat(i,'[data-id="').concat(t.parent,'"]'))}},{key:"elementIsAncestorOfItem",value:function(e,t){return!!this.getParentNodeOfItem(e,t,"li")}},{key:"getDirectListParentOfItem",value:function(e,t){return this.getParentNodeOfItem(e,t,"ol")}},{key:"maybeAppendItemToParentDom",value:function(e){var t=this,i=e.parent,s=this.sortedDataDomArray.find((function(i){return t.elementIsParentOfItem(i,e)||t.elementIsAncestorOfItem(i,e)}));if(!s)return!1;var a=this.createItemElement(e),r=this.getDirectListParentOfItem(s,e);r||(r=this.createItemElement({id:i},"ol"),(this.getParentNodeOfItem(s,e,"li")||s).appendChild(r));return r.appendChild(a),!0}},{key:"getListItemsDom",value:function(){var e=this;this.sortedDataDomArray=[];for(var t=[];t.length!==this.sortListItems().length;)t=this.sortedData.reduce((function(t,i){var s,a=i.id.toString();if(t.includes(a))return t;if(i.parent)s=e.maybeAppendItemToParentDom(i);else{var r=e.createItemElement(i);e.sortedDataDomArray.push(r),s=!0}return s&&t.push(a),t}),t);return this.sortedDataDomArray}},{key:"convertDomToData",value:function(e){var t=this;return Array.from((null==e?void 0:e.querySelectorAll("li"))||[]).map((function(e){var i,a=e.parentNode,r=a.dataset.id,n=Array.from(a.children).findIndex((function(t){return t===e}))+1;return s(i={},t.getItemPropProxyName("id"),e.dataset.id),s(i,t.getItemPropProxyName("parent"),r),s(i,t.getItemPropProxyName("order"),n),i}))}},{key:"render",value:function(){var e=document.createElement("ol");return this.getListItemsDom().forEach((function(t){return e.appendChild(t)})),e}}]),t}();return function(){function t(i){var a=i.actions,r=void 0===a?{}:a,n=i.data,o=i.droppingEdge,l=void 0===o?15:o,d=i.el,h=i.init,c=void 0===h||h,u=i.listClassNames,g=i.listItemClassNames,f=i.nestingLevels,v=i.propertyMap,p=void 0===v?{}:v;e(this,t),s(this,"actions",void 0),s(this,"classNames",void 0),s(this,"cursor",void 0),s(this,"data",void 0),s(this,"dataEngine",void 0),s(this,"distances",void 0),s(this,"draggedNode",void 0),s(this,"initialised",void 0),s(this,"listClassNames",void 0),s(this,"listEventListeners",void 0),s(this,"listInterface",void 0),s(this,"listItemClassNames",void 0),s(this,"mainListClassName",void 0),s(this,"nestingLevels",void 0),s(this,"placeholderList",void 0),s(this,"placeholderInUse",void 0),s(this,"propertyMap",void 0),s(this,"sortableList",void 0),s(this,"targetedNode",void 0),s(this,"targetNode",void 0),s(this,"wrapper",void 0);var m="string"==typeof d?document.querySelector(d):d,y=m instanceof HTMLOListElement||m instanceof HTMLUListElement;this.wrapper=y?void 0:m,this.sortableList=y?m:null,this.data=n,this.listClassNames=this.createListClassNamesArray(u),this.mainListClassName=this.listClassNames[0]||"nested-sort",this.listItemClassNames=this.createListClassNamesArray(g),this.propertyMap=p,this.actions={onDrop:r.onDrop},this.initialised=!1,this.distances={droppingEdge:l},this.classNames={dragged:"ns-dragged",placeholder:"ns-placeholder",targeted:"ns-targeted"},this.listEventListeners={dragover:this.onDragOver.bind(this),dragstart:this.onDragStart.bind(this),dragenter:this.onDragEnter.bind(this),dragend:this.onDragEnd.bind(this),drop:this.onDrop.bind(this)};var L=parseInt(f);this.nestingLevels=isNaN(L)?-1:L,this.listInterface=this.getListInterface(),this.maybeInitDataDom(),this.addListAttributes(),c&&this.initDragAndDrop()}return i(t,[{key:"getListInterface",value:function(){return Array.isArray(this.data)&&this.data.length||this.sortableList instanceof HTMLOListElement?HTMLOListElement:HTMLUListElement}},{key:"getDataEngine",value:function(){return this.dataEngine||(this.dataEngine=new n({data:this.data,propertyMap:this.propertyMap})),this.dataEngine}},{key:"createListClassNamesArray",value:function(e){return e?Array.isArray(e)?e:e.split(" "):[]}},{key:"maybeInitDataDom",value:function(){if(Array.isArray(this.data)&&this.data.length&&this.wrapper){var e=this.getDataEngine().render();this.wrapper.innerHTML="",this.wrapper.appendChild(e)}}},{key:"getListTagName",value:function(){return this.listInterface===HTMLOListElement?"ol":"ul"}},{key:"getSortableList",value:function(){var e;return this.sortableList instanceof this.listInterface||(this.sortableList=null===(e=this.wrapper)||void 0===e?void 0:e.querySelector(this.getListTagName())),this.sortableList}},{key:"addListAttributes",value:function(){var e,t=this,i=this.getSortableList();i&&((e=i.classList).add.apply(e,a(this.listClassNames.concat(this.mainListClassName))),i.querySelectorAll(this.getListTagName()).forEach((function(e){var i;(i=e.classList).add.apply(i,a(t.listClassNames))})),i.querySelectorAll("li").forEach((function(e){var i;(i=e.classList).add.apply(i,a(t.listItemClassNames))})))}},{key:"toggleMainListLifeCycleClassName",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.getSortableList();if(t){var i="".concat(this.mainListClassName,"--enabled");e?t.classList.add(i):t.classList.remove(i)}}},{key:"toggleListItemAttributes",value:function(){var e,t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];null===(e=this.getSortableList())||void 0===e||e.querySelectorAll("li").forEach((function(e){e.setAttribute("draggable",t.toString())}))}},{key:"toggleListEventListeners",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],i=this.getSortableList();i&&Object.keys(this.listEventListeners).forEach((function(s){t?i.removeEventListener(s,e.listEventListeners[s]):i.addEventListener(s,e.listEventListeners[s],!1)}))}},{key:"initDragAndDrop",value:function(){this.initialised||(this.toggleListEventListeners(),this.initPlaceholderList(),this.toggleListItemAttributes(),this.toggleMainListLifeCycleClassName(),this.initialised=!0)}},{key:"init",value:function(){this.initDragAndDrop()}},{key:"destroy",value:function(){this.toggleListEventListeners(!0),this.toggleListItemAttributes(!1),this.toggleMainListLifeCycleClassName(!1),this.initialised=!1}},{key:"removeClassFromEl",value:function(e,t){t&&t.classList.contains(e)&&t.classList.remove(e)}},{key:"canBeTargeted",value:function(e){return!(!this.draggedNode||this.draggedNode===e)&&("LI"===e.nodeName||e instanceof this.listInterface&&e.classList.contains(this.classNames.placeholder))}},{key:"onDragStart",value:function(e){var t;this.draggedNode=e.target,this.draggedNode.classList.add(this.classNames.dragged),null===(t=e.dataTransfer)||void 0===t||t.setData("text","Drag started!")}},{key:"onDragOver",value:function(e){e.preventDefault(),this.updateCoordination(e),this.managePlaceholderLists()}},{key:"onDragEnter",value:function(e){this.canBeTargeted(e.target)&&(this.removeClassFromEl(this.classNames.targeted,this.targetedNode),this.targetedNode=e.target,this.targetedNode.classList.add(this.classNames.targeted))}},{key:"onDragEnd",value:function(e){e.stopPropagation(),this.removeClassFromEl(this.classNames.dragged,this.draggedNode),this.removeClassFromEl(this.classNames.targeted,this.targetedNode),this.cleanupPlaceholderLists(),delete this.draggedNode,delete this.targetedNode}},{key:"onDrop",value:function(e){e.stopPropagation(),this.maybeDrop(),this.cleanupPlaceholderLists(),"function"==typeof this.actions.onDrop&&this.actions.onDrop(this.getDataEngine().convertDomToData(this.getSortableList()))}},{key:"updateCoordination",value:function(e){this.calcMouseCoords(e),this.calcMouseToTargetedElDist()}},{key:"getDropLocation",value:function(){if(this.canBeDropped()){var e;if("LI"===(null===(e=this.targetedNode)||void 0===e?void 0:e.nodeName))return"before";if(this.targetedNode instanceof this.listInterface)return"inside"}}},{key:"maybeDrop",value:function(){var e=this.getDropLocation();e&&this.dropTheItem(e)}},{key:"dropTheItem",value:function(e){var t,i,s;switch(e){case"before":null===(t=this.targetedNode)||void 0===t||null===(i=t.parentNode)||void 0===i||i.insertBefore(this.draggedNode,this.targetedNode);break;case"inside":null===(s=this.targetedNode)||void 0===s||s.appendChild(this.draggedNode)}}},{key:"calcMouseCoords",value:function(e){this.cursor={X:e.clientX,Y:e.clientY}}},{key:"calcMouseToTargetedElDist",value:function(){if(this.targetedNode){var e=this.targetedNode.getBoundingClientRect();this.targetNode={X:e.left,Y:e.top};var t=this.targetNode.Y-this.cursor.Y,i=Math.abs(t);this.distances.mouseTo={targetedElTop:t,targetedElTopAbs:i,targetedElBot:i-this.targetedNode.clientHeight}}}},{key:"areNested",value:function(e,t){return!!e&&!!t&&Array.from(null==t?void 0:t.querySelectorAll("li")).some((function(t){return t===e}))}},{key:"cursorIsIndentedEnough",value:function(){return this.cursor.X-this.targetNode.X>50}},{key:"mouseIsTooCloseToTop",value:function(){var e;return!(null===(e=this.distances)||void 0===e||!e.droppingEdge)&&this.cursor.Y-this.targetNode.Y<this.distances.droppingEdge}},{key:"managePlaceholderLists",value:function(){var e=this;this.analysePlaceHolderSituation().forEach((function(t){switch(t){case"add":e.cleanupPlaceholderLists(),e.addPlaceholderList();break;case"cleanup":e.cleanupPlaceholderLists()}}))}},{key:"targetedNodeIsPlaceholder",value:function(){return this.targetedNode instanceof this.listInterface&&this.targetedNode.classList.contains(this.classNames.placeholder)}},{key:"getTargetedNodeDepth",value:function(){for(var e=0,t=this.targetedNode,i=this.getSortableList();i!==(null===(s=t)||void 0===s?void 0:s.parentElement);){var s,a,r;(null===(a=t)||void 0===a?void 0:a.parentElement)instanceof this.listInterface&&e++,t=null===(r=t)||void 0===r?void 0:r.parentElement}return e}},{key:"nestingThresholdReached",value:function(){return!(this.nestingLevels<0)&&(0===this.nestingLevels||this.getTargetedNodeDepth()>=this.nestingLevels)}},{key:"analysePlaceHolderSituation",value:function(){if(!this.targetedNode||this.areNested(this.targetedNode,this.draggedNode))return[];var e=[];return!this.cursorIsIndentedEnough()||this.mouseIsTooCloseToTop()?this.targetedNodeIsPlaceholder()||e.push("cleanup"):this.targetedNode===this.draggedNode||"LI"!==this.targetedNode.nodeName||this.targetedNode.querySelectorAll(this.getListTagName()).length||this.nestingThresholdReached()||e.push("add"),e}},{key:"animatePlaceholderList",value:function(){var e;this.placeholderInUse.style.minHeight="0",this.placeholderInUse.style.transition="min-height ease .2s",this.placeholderInUse.style.minHeight="".concat(null===(e=this.draggedNode)||void 0===e?void 0:e.offsetHeight,"px")}},{key:"addPlaceholderList",value:function(){var e;this.getPlaceholderList(),null===(e=this.targetedNode)||void 0===e||e.appendChild(this.placeholderInUse),this.animatePlaceholderList()}},{key:"targetNodeIsIdentified",value:function(){return!!this.targetedNode}},{key:"targetNodeIsBeingDragged",value:function(){return this.targetNodeIsIdentified()&&this.targetedNode===this.draggedNode}},{key:"targetNodeIsListWithItems",value:function(){return this.targetNodeIsIdentified()&&this.targetedNode instanceof this.listInterface&&!!this.targetedNode.querySelectorAll("li").length}},{key:"canBeDropped",value:function(){return this.targetNodeIsIdentified()&&!this.targetNodeIsBeingDragged()&&!this.targetNodeIsListWithItems()&&!this.areNested(this.targetedNode,this.draggedNode)}},{key:"cleanupPlaceholderLists",value:function(){var e,t=this,i=this.getListTagName(),s=(null===(e=this.getSortableList())||void 0===e?void 0:e.querySelectorAll(i))||[];Array.from(s).forEach((function(e){e.querySelectorAll("li").length?e.classList.contains(t.classNames.placeholder)&&(e.classList.remove(t.classNames.placeholder),e.style.minHeight="auto",e.dataset.id=e.parentNode.dataset.id):e.remove()}))}},{key:"initPlaceholderList",value:function(){var e;this.placeholderList=document.createElement(this.getListTagName()),(e=this.placeholderList.classList).add.apply(e,[this.classNames.placeholder].concat(a(this.listClassNames)))}},{key:"getPlaceholderList",value:function(){return this.placeholderInUse=this.placeholderList.cloneNode(!0),this.placeholderInUse}}]),t}()})); |
{ | ||
"name": "nested-sort", | ||
"version": "5.0.0", | ||
"author": "Hesam Bahrami (Genzo)", | ||
"description": "A JavaScript library to create a nested list of elements", | ||
"version": "5.0.1", | ||
"author": "Hesam Bahrami (hesamurai)", | ||
"description": "A JavaScript library for sorting a nested list of items via drag and drop.", | ||
"umdClassName": "NestedSort", | ||
"main": "dist/nested-sort.cjs.js", | ||
@@ -16,22 +17,30 @@ "module": "dist/nested-sort.esm.js", | ||
"devDependencies": { | ||
"@babel/core": "7.9.0", | ||
"@babel/core": "7.12.7", | ||
"@babel/plugin-proposal-class-properties": "7.12.1", | ||
"@babel/plugin-proposal-object-rest-spread": "7.12.1", | ||
"@babel/plugin-transform-runtime": "^7.11.5", | ||
"@babel/preset-env": "7.9.5", | ||
"babel-core": "7.0.0-bridge.0", | ||
"@babel/preset-env": "7.12.7", | ||
"@babel/preset-typescript": "7.12.7", | ||
"@rollup/plugin-babel": "5.2.1", | ||
"@rollup/plugin-commonjs": "16.0.0", | ||
"@rollup/plugin-eslint": "^8.0.1", | ||
"@rollup/plugin-node-resolve": "10.0.0", | ||
"@typescript-eslint/eslint-plugin": "^4.14.1", | ||
"@typescript-eslint/parser": "^4.14.1", | ||
"babel-jest": "24.9.0", | ||
"concurrently": "5.3.0", | ||
"eslint": "^7.21.0", | ||
"husky": "^4.2.5", | ||
"jest": "26.6.3", | ||
"jsdom": "^16.4.0", | ||
"rollup": "1.32.1", | ||
"rollup-plugin-babel": "4.4.0", | ||
"rollup-plugin-commonjs": "10.1.0", | ||
"rollup-plugin-eslint": "^7.0.0", | ||
"rollup-plugin-node-resolve": "5.2.0", | ||
"rollup-plugin-terser": "^6.1.0", | ||
"serve": "11.3.2" | ||
"rollup": "2.33.3", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"serve": "11.3.2", | ||
"typescript": "4.1.2" | ||
}, | ||
"scripts": { | ||
"prepare": "yarn build", | ||
"build": "rollup -c", | ||
"build": "yarn build:types && yarn build:js", | ||
"build:js": "rollup -c", | ||
"build:types": "tsc --emitDeclarationOnly", | ||
"build:watch": "rollup -c -w", | ||
@@ -38,0 +47,0 @@ "watch": "concurrently 'yarn build:watch' 'yarn serve -l tcp://127.0.0.1'", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
106360
2264
22
10
1