import { ChangeDetectorRef } from '@angular/core' ; import { Directive , Input , Output , EventEmitter , ElementRef } from '@angular/core' ; import { FormArray } from '@angular/forms' ; import { AbstractComponent , AbstractHandleComponent } from './abstract.component' ; import { DragDropConfig } from './dnd.config' ; import { DragDropService , DragDropSortableService } from './dnd.service' ; @ Directive ( { selector : '[dnd-sortable-container]' } ) export class SortableContainer extends AbstractComponent { @ Input ( "dragEnabled" ) set draggable ( value ) { this . dragEnabled = ! ! value ; } private _sortableData : Array < any > | FormArray = [ ] ; private sortableHandler : SortableFormArrayHandler | SortableArrayHandler ; @ Input ( ) set sortableData ( sortableData ) { this . _sortableData = sortableData ; if ( sortableData instanceof FormArray ) { this . sortableHandler = new SortableFormArrayHandler ( ) ; } else { this . sortableHandler = new SortableArrayHandler ( ) ; } this . dropEnabled = ! ! this . _sortableData ; } get sortableData ( ) : Array < any > | FormArray { return this . _sortableData ; } @ Input ( "dropZones" ) set dropzones ( value ) { this . dropZones = value ; } constructor ( elemRef , dragDropService , config , cdr , private _sortableDataService ) { super ( elemRef , dragDropService , config , cdr ) ; this . dragEnabled = false ; } _onDragEnterCallback ( event ) { if ( this . _sortableDataService . isDragged ) { let item = this . _sortableDataService . sortableContainer . getItemAt ( this . _sortableDataService . index ) ; if ( this . indexOf ( item ) === - 1 ) { this . _sortableDataService . sortableContainer . removeItemAt ( this . _sortableDataService . index ) ; if ( this . _sortableDataService . sortableContainer . _sortableData . length === 0 ) { this . _sortableDataService . sortableContainer . dropEnabled = true ; } this . insertItemAt ( item , 0 ) ; this . _sortableDataService . sortableContainer = this ; this . _sortableDataService . index = 0 ; } this . detectChanges ( ) ; } } getItemAt ( index ) { return this . sortableHandler . getItemAt ( this . _sortableData , index ) ; } indexOf ( item ) { return this . sortableHandler . indexOf ( this . _sortableData , item ) ; } removeItemAt ( index ) { this . sortableHandler . removeItemAt ( this . _sortableData , index ) ; } insertItemAt ( item , index ) { this . sortableHandler . insertItemAt ( this . _sortableData , item , index ) ; } } class SortableArrayHandler { getItemAt ( sortableData , index ) { return sortableData [ index ] ; } indexOf ( sortableData , item ) { return sortableData . indexOf ( item ) ; } removeItemAt ( sortableData , index ) { sortableData . splice ( index , 1 ) ; } insertItemAt ( sortableData , item , index ) { sortableData . splice ( index , 0 , item ) ; } } class SortableFormArrayHandler { getItemAt ( sortableData , index ) { return sortableData . at ( index ) ; } indexOf ( sortableData , item ) { return sortableData . controls . indexOf ( item ) ; } removeItemAt ( sortableData , index ) { sortableData . removeAt ( index ) ; } insertItemAt ( sortableData , item , index ) { sortableData . insert ( index , item ) ; } } @ Directive ( { selector : '[dnd-sortable]' } ) export class SortableComponent extends AbstractComponent { @ Input ( 'sortableIndex' ) index : number ; @ Input ( "dragEnabled" ) set draggable ( value ) { this . dragEnabled = ! ! value ; } @ Input ( "dropEnabled" ) set droppable ( value ) { this . dropEnabled = ! ! value ; } /**
     * The data that has to be dragged. It can be any JS object
     */ @ Input ( ) dragData : any ; /**
     * Drag allowed effect
     */ @ Input ( "effectAllowed" ) set effectallowed ( value ) { this . effectAllowed = value ; } /**
     * Drag effect cursor
     */ @ Input ( "effectCursor" ) set effectcursor ( value ) { this . effectCursor = value ; } /**
     * Callback function called when the drag action ends with a valid drop action.
     * It is activated after the on-drop-success callback
     */ @ Output ( "onDragSuccess" ) onDragSuccessCallback : EventEmitter < any > = new EventEmitter < any > ( ) ; @ Output ( "onDragStart" ) onDragStartCallback : EventEmitter < any > = new EventEmitter < any > ( ) ; @ Output ( "onDragOver" ) onDragOverCallback : EventEmitter < any > = new EventEmitter < any > ( ) ; @ Output ( "onDragEnd" ) onDragEndCallback : EventEmitter < any > = new EventEmitter < any > ( ) ; @ Output ( "onDropSuccess" ) onDropSuccessCallback : EventEmitter < any > = new EventEmitter < any > ( ) ; constructor ( elemRef , dragDropService , config , private _sortableContainer , private _sortableDataService , cdr ) { super ( elemRef , dragDropService , config , cdr ) ; this . dropZones = this . _sortableContainer . dropZones ; this . dragEnabled = true ; this . dropEnabled = true ; } _onDragStartCallback ( event ) { this . _sortableDataService . isDragged = true ; this . _sortableDataService . sortableContainer = this . _sortableContainer ; this . _sortableDataService . index = this . index ; this . _sortableDataService . markSortable ( this . _elem ) ; this . _dragDropService . isDragged = true ; this . _dragDropService . dragData = this . dragData ; this . _dragDropService . onDragSuccessCallback = this . onDragSuccessCallback ; this . onDragStartCallback . emit ( this . _dragDropService . dragData ) ; } _onDragOverCallback ( event ) { if ( this . _sortableDataService . isDragged && this . _elem !== this . _sortableDataService . elem ) { this . _sortableDataService . sortableContainer = this . _sortableContainer ; this . _sortableDataService . index = this . index ; this . _sortableDataService . markSortable ( this . _elem ) ; this . onDragOverCallback . emit ( this . _dragDropService . dragData ) ; } } _onDragEndCallback ( event ) { this . _sortableDataService . isDragged = false ; this . _sortableDataService . sortableContainer = null ; this . _sortableDataService . index = null ; this . _sortableDataService . markSortable ( null ) ; this . _dragDropService . isDragged = false ; this . _dragDropService . dragData = null ; this . _dragDropService . onDragSuccessCallback = null ; this . onDragEndCallback . emit ( this . _dragDropService . dragData ) ; } _onDragEnterCallback ( event ) { if ( this . _sortableDataService . isDragged ) { this . _sortableDataService . markSortable ( this . _elem ) ; if ( ( this . index !== this . _sortableDataService . index ) || ( this . _sortableDataService . sortableContainer . sortableData !== this . _sortableContainer . sortableData ) ) { let item = this . _sortableDataService . sortableContainer . getItemAt ( this . _sortableDataService . index ) ; this . _sortableDataService . sortableContainer . removeItemAt ( this . _sortableDataService . index ) ; if ( this . _sortableDataService . sortableContainer . sortableData . length === 0 ) { this . _sortableDataService . sortableContainer . dropEnabled = true ; } this . _sortableContainer . insertItemAt ( item , this . index ) ; if ( this . _sortableContainer . dropEnabled ) { this . _sortableContainer . dropEnabled = false ; } this . _sortableDataService . sortableContainer = this . _sortableContainer ; this . _sortableDataService . index = this . index ; this . detectChanges ( ) ; } } } _onDropCallback ( event ) { if ( this . _sortableDataService . isDragged ) { this . onDropSuccessCallback . emit ( this . _dragDropService . dragData ) ; if ( this . _dragDropService . onDragSuccessCallback ) { this . _dragDropService . onDragSuccessCallback . emit ( this . _dragDropService . dragData ) ; } this . _sortableContainer . detectChanges ( ) ; } } } @ Directive ( { selector : '[dnd-sortable-handle]' } ) export class SortableHandleComponent extends AbstractHandleComponent { constructor ( elemRef , dragDropService , config , _Component , cdr ) { super ( elemRef , dragDropService , config , _Component , cdr ) ; } }