import { Subject } from 'rxjs'; export class SortElement { enable: boolean = true; currentElementDragged!: HTMLElement; currentElementUnder: HTMLElement | undefined; currentEditedElement!: HTMLElement; currentElementDraggedRef!: HTMLElement; containerItems!: HTMLElement; currentElement: any; _insertBeforeEvent = new Subject(); _appendElementEvent = new Subject(); onInsertBeforeEvent = this._insertBeforeEvent.asObservable(); onAppendElementEvent = this._appendElementEvent.asObservable(); setContainerItem(element: HTMLElement) { this.containerItems = element; } onDragStart({ currentTarget }: DragEvent, element: HTMLElement) { this.currentElementDragged = currentTarget; this.currentElementDraggedRef = element; } onDragEnd = () => (this.currentElementUnder = undefined); onDragOver({ currentTarget }: DragEvent, element: HTMLElement) { let item = currentTarget; if ( this.currentElementUnder === item || this.currentElementDragged === item ) return; let isChildren = Array.from(this.containerItems.children).includes(item); if (!isChildren) return; if (!this.currentElementUnder) { this.currentElementUnder = item; this._changePosition(this.currentElementUnder, element); return; } this.currentElementUnder = item; this._changePosition(this.currentElementUnder, element); } private _changePosition(currentElementUnder: any, element: HTMLElement) { let parentNode = currentElementUnder.parentNode; let { elementReferenceEdit, elementReferenceParent } = this._getReferenceItems(parentNode, currentElementUnder, element); if (elementReferenceEdit) this._insertBeforeElement( parentNode, elementReferenceParent, elementReferenceEdit ); else this._appendElement(parentNode, elementReferenceParent); } private _insertBeforeElement( parentNode: any, elementReferenceParent: any, elementReferenceEdit: any ) { if ( !( this.currentElementDragged?.parentElement && elementReferenceEdit?.parentElement ) ) return; parentNode.insertBefore(this.currentElementDragged, elementReferenceEdit); this._insertBeforeEvent.next({ currentElementDraggedRef: this.currentElementDraggedRef, elementReferenceParent, }); } private _appendElement(parentNode: any, elementReferenceParent: HTMLElement) { parentNode.appendChild(this.currentElementDragged); this._appendElementEvent.next({ elementReferenceParent, currentElementDraggedRef: this.currentElementDraggedRef, }); } private _getReferenceItems( parentNode: any, currentElementUnder: any, element: HTMLElement ) { let indexCurrentElementDragged = Array.from(parentNode.children).indexOf( this.currentElementDragged ); let indexCurrentElementUnder = Array.from(parentNode.children).indexOf( this.currentElementUnder ); let elementReferenceEdit: any; let elementReferenceParent: any; if (indexCurrentElementUnder > indexCurrentElementDragged) { elementReferenceEdit = currentElementUnder.nextElementSibling; if (element) elementReferenceParent = element.nextElementSibling; } else { elementReferenceEdit = currentElementUnder; if (element) elementReferenceParent = element; } return { elementReferenceEdit, elementReferenceParent }; } }