all files / component/dragdrop/ draggable.directive.ts

76.12% Statements 51/67
42.31% Branches 11/26
90% Functions 9/10
74.6% Lines 47/63
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123                      524× 524× 524× 524× 524×   524×     918× 918×       42×     524× 524×   524×                                                                                   524×                              
/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
import { Directive, ElementRef, HostBinding, Input, OnDestroy, Optional } from '@angular/core';
import { fromEvent as observableFromEvent } from 'rxjs';
import { filter, first, takeWhile } from 'rxjs/operators';
import { DejaClipboardService } from '../../common/core/clipboard/clipboard.service';
import { UUID } from '../../common/core/UUID';
 
@Directive({
    selector: '[deja-draggable]',
})
export class DejaDraggableDirective implements OnDestroy {
    @HostBinding('attr.draggable') public draggable: boolean = null;
    @HostBinding('attr.dragdropid') private dragdropid: string;
    private draginfokey = 'draginfos';
    private objectKey = 'object';
    private elementKey = 'element';
    private uuidKey = 'uuid';
    private _context: IDejaDragContext;
    private isAlive = true;
 
    @Input('deja-draggable')
    public set context(value: IDejaDragContext) {
        this._context = value;
        this.draggable = !!value ? true : null;
    }
 
    public get context() {
        return this._context;
    }
 
    constructor(elementRef: ElementRef, @Optional() private clipboardService: DejaClipboardService) {
        const element = elementRef.nativeElement as HTMLElement;
 
        observableFromEvent(element, 'dragstart').pipe(
            takeWhile(() => this.isAlive),
            filter(() => !!this.context))
            .subscribe((event: DragEvent) => {
                Iif (!clipboardService) {
                    throw new Error('To use the DejaDraggableDirective, please import and provide the DejaClipboardService in your application.');
                }
 
                // console.log('dragstart');
                const dragInfos = {} as { [key: string]: any };
                this.dragdropid = new UUID().toString();
                dragInfos[this.uuidKey] = this.dragdropid;
 
                const object = (this.context && this.context.object) || element;
                dragInfos[this.objectKey] = object;
                dragInfos[this.elementKey] = element;
 
                this.clipboardService.set(this.draginfokey, dragInfos);
 
                let data = 'notavailable';
                Eif (object) {
                    object.dragged = true;
                    data = JSON.stringify(data);
                }
 
                Eif (this.context && this.context.dragstartcallback) {
                    const e = event as IDejaDragEvent;
                    e.dragInfo = dragInfos;
                    e.dragObject = this.context.object;
                    e.dragElement = element;
                    this.context.dragstartcallback(e);
                    event.dataTransfer.setData('text/plain', data);
                    Iif (e.defaultPrevented) {
                        event.preventDefault();
                    }
                }
 
                observableFromEvent(element, 'dragend').pipe(
                    takeWhile(() => this.isAlive),
                    first())
                    .subscribe((evt: DragEvent) => {
                        // console.log('dragend');
                        const dragEndInfos = this.clipboardService.get(this.draginfokey) as { [key: string]: any };
                        const obj = dragEndInfos && dragEndInfos[this.objectKey];
                        if (obj) {
                            delete obj.dragged;
                        }
 
                        if (this.context && this.context.dragendcallback && dragEndInfos) {
                            const e = evt as IDejaDragEvent;
                            e.dragInfo = dragEndInfos;
                            e.dragObject = obj;
                            e.dragElement = dragEndInfos[this.elementKey];
                            this.context.dragendcallback(e);
 
                            if (e.defaultPrevented) {
                                evt.stopPropagation();
                            }
                        }
 
                        this.clipboardService.clear();
                        this.dragdropid = undefined;
                    });
            });
    }
 
    public ngOnDestroy() {
        this.isAlive = false;
    }
}
 
export interface IDejaDragEvent extends DragEvent {
    dragInfo: { [key: string]: any };
    dragObject: any;
    dragElement: HTMLElement;
}
 
export interface IDejaDragContext {
    object?: any;
    dragstartcallback?(event: IDejaDragEvent): void;
    dragendcallback?(event: IDejaDragEvent): void;
}