import { Injectable , ChangeDetectorRef , ViewRef } from '@angular/core' ; import { ElementRef } from '@angular/core' ; import { DragDropConfig , DragImage } from './dnd.config' ; import { DragDropService } from './dnd.service' ; import { isString , isFunction , isPresent , createImage , callFun } from './dnd.utils' ; @ Injectable ( ) export abstract class AbstractComponent { _elem : HTMLElement ; _dragHandle : HTMLElement ; _dragHelper : HTMLElement ; _defaultCursor : string ; /**
     * Last element that was mousedown'ed
     */ _target : EventTarget ; /**
     * Whether the object is draggable. Default is true.
     */ private _dragEnabled : boolean = false ; set dragEnabled ( enabled ) { this . _dragEnabled = ! ! enabled ; this . _elem . draggable = this . _dragEnabled ; } get dragEnabled ( ) : boolean { return this . _dragEnabled ; } /**
     * Allows drop on this element
     */ dropEnabled : boolean = false ; /**
     * Drag effect
     */ effectAllowed : string ; /**
     * Drag cursor
     */ effectCursor : string ; /**
     * Restrict places where a draggable element can be dropped. Either one of
     * these two mechanisms can be used:
     *
     * - dropZones: an array of strings that permits to specify the drop zones
     *   associated with this component. By default, if the drop-zones attribute
     *   is not specified, the droppable component accepts drop operations by
     *   all the draggable components that do not specify the allowed-drop-zones
     *
     * - allowDrop: a boolean function for droppable components, that is checked
     *   when an item is dragged. The function is passed the dragData of this
     *   item.
     *   - if it returns true, the item can be dropped in this component
     *   - if it returns false, the item cannot be dropped here
     */ allowDrop : ( dropData : any ) => boolean ; dropZones : string [ ] = [ ] ; /**
     * Here is the property dragImage you can use:
     * - The string value as url to the image
     *   <div class="panel panel-default"
     *        dnd-draggable [dragEnabled]="true"
     *        [dragImage]="/images/simpler.png">
     * ...
     * - The DragImage value with Image and optional offset by x and y:
     *   let myDragImage: DragImage = new DragImage("/images/simpler1.png", 0, 0);
     * ...
     *   <div class="panel panel-default"
     *        dnd-draggable [dragEnabled]="true"
     *        [dragImage]="myDragImage">
     * ...
     * - The custom function to return the value of dragImage programmatically:
     *   <div class="panel panel-default"
     *        dnd-draggable [dragEnabled]="true"
     *        [dragImage]="getDragImage(someData)">
     * ...
     *   getDragImage(value:any): string {
     *     return value ? "/images/simpler1.png" : "/images/simpler2.png"
     *   }
     */ dragImage : string | DragImage | Function ; cloneItem : boolean = false ; constructor ( elemRef , public _dragDropService , public _config , private _cdr ) { this . _defaultCursor = _config . defaultCursor ; this . _elem = elemRef . nativeElement ; this . _elem . style . cursor = this . _defaultCursor ; this . _elem . ondragenter = ( event ) => { this . _onDragEnter ( event ) ; } ; this . _elem . ondragover = ( event ) => { this . _onDragOver ( event ) ; if ( event . dataTransfer != null ) { event . dataTransfer . dropEffect = this . _config . dropEffect . name ; } return false ; } ; this . _elem . ondragleave = ( event ) => { this . _onDragLeave ( event ) ; } ; this . _elem . ondrop = ( event ) => { this . _onDrop ( event ) ; } ; this . _elem . onmousedown = ( event ) => { this . _target = event . target ; } ; this . _elem . ondragstart = ( event ) => { if ( this . _dragHandle ) { if ( ! this . _dragHandle . contains ( < Element > this . _target ) ) { event . preventDefault ( ) ; return ; } } this . _onDragStart ( event ) ; if ( event . dataTransfer != null ) { event . dataTransfer . setData ( 'text' , '' ) ; event . dataTransfer . effectAllowed = this . effectAllowed || this . _config . dragEffect . name ; if ( isPresent ( this . dragImage ) ) { if ( isString ( this . dragImage ) ) { ( < any > event . dataTransfer ) . setDragImage ( createImage ( < string > this . dragImage ) ) ; } else if ( isFunction ( this . dragImage ) ) { ( < any > event . dataTransfer ) . setDragImage ( callFun ( < Function > this . dragImage ) ) ; } else { let img = < DragImage > this . dragImage ; ( < any > event . dataTransfer ) . setDragImage ( img . imageElement , img . x_offset , img . y_offset ) ; } } else if ( isPresent ( this . _config . dragImage ) ) { let dragImage = this . _config . dragImage ; ( < any > event . dataTransfer ) . setDragImage ( dragImage . imageElement , dragImage . x_offset , dragImage . y_offset ) ; } else if ( this . cloneItem ) { this . _dragHelper = < HTMLElement > this . _elem . cloneNode ( true ) ; this . _dragHelper . classList . add ( 'dnd-drag-item' ) ; this . _dragHelper . style . position = "absolute" ; this . _dragHelper . style . top = "0px" ; this . _dragHelper . style . left = "-1000px" ; this . _elem . parentElement . appendChild ( this . _dragHelper ) ; ( < any > event . dataTransfer ) . setDragImage ( this . _dragHelper , event . offsetX , event . offsetY ) ; } let cursorelem = ( this . _dragHandle ) ? this . _dragHandle : this . _elem ; if ( this . _dragEnabled ) { cursorelem . style . cursor = this . effectCursor ? this . effectCursor : this . _config . dragCursor ; } else { cursorelem . style . cursor = this . _defaultCursor ; } } } ; this . _elem . ondragend = ( event ) => { if ( this . _elem . parentElement && this . _dragHelper ) { this . _elem . parentElement . removeChild ( this . _dragHelper ) ; } this . _onDragEnd ( event ) ; let cursorelem = ( this . _dragHandle ) ? this . _dragHandle : this . _elem ; cursorelem . style . cursor = this . _defaultCursor ; } ; } public setDragHandle ( elem ) { this . _dragHandle = elem ; } /******* Change detection ******/ detectChanges ( ) { setTimeout ( ( ) => { if ( this . _cdr && ! ( this . _cdr as ViewRef ) . destroyed ) { this . _cdr . detectChanges ( ) ; } } , 250 ) ; } private _onDragEnter ( event ) { if ( this . _isDropAllowed ( event ) ) { this . _onDragEnterCallback ( event ) ; } } private _onDragOver ( event ) { if ( this . _isDropAllowed ( event ) ) { if ( event . preventDefault ) { event . preventDefault ( ) ; } this . _onDragOverCallback ( event ) ; } } private _onDragLeave ( event ) { if ( this . _isDropAllowed ( event ) ) { this . _onDragLeaveCallback ( event ) ; } } private _onDrop ( event ) { if ( this . _isDropAllowed ( event ) ) { this . _preventAndStop ( event ) ; this . _onDropCallback ( event ) ; this . detectChanges ( ) ; } } private _isDropAllowed ( event ) { if ( ( this . _dragDropService . isDragged || ( event . dataTransfer && event . dataTransfer . files ) ) && this . dropEnabled ) { if ( this . allowDrop ) { return this . allowDrop ( this . _dragDropService . dragData ) ; } if ( this . dropZones . length === 0 && this . _dragDropService . allowedDropZones . length === 0 ) { return true ; } for ( let i = 0 ; i < this . _dragDropService . allowedDropZones . length ; i ++ ) { let dragZone = this . _dragDropService . allowedDropZones [ i ] ; if ( this . dropZones . indexOf ( dragZone ) !== - 1 ) { return true ; } } } return false ; } private _preventAndStop ( event ) { if ( event . preventDefault ) { event . preventDefault ( ) ; } if ( event . stopPropagation ) { event . stopPropagation ( ) ; } } private _onDragStart ( event ) { if ( this . _dragEnabled ) { this . _dragDropService . allowedDropZones = this . dropZones ; this . _onDragStartCallback ( event ) ; } } private _onDragEnd ( event ) { this . _dragDropService . allowedDropZones = [ ] ; this . _onDragEndCallback ( event ) ; } _onDragEnterCallback ( event ) { } _onDragOverCallback ( event ) { } _onDragLeaveCallback ( event ) { } _onDropCallback ( event ) { } _onDragStartCallback ( event ) { } _onDragEndCallback ( event ) { } } export class AbstractHandleComponent { _elem : HTMLElement ; constructor ( elemRef , public _dragDropService , public _config , private _Component , private _cdr ) { this . _elem = elemRef . nativeElement ; this . _Component . setDragHandle ( this . _elem ) ; } }