all files / component/mouse-dragdrop/ mouse-dragdrop-cursor.component.ts

92.96% Statements 66/71
67.31% Branches 35/52
100% Functions 21/21
92.65% Lines 63/68
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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139                                                                                                                                              12×          
/*
 *  @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 { Component, ElementRef, OnDestroy, ViewChild, ViewEncapsulation } from '@angular/core';
import { BehaviorSubject, from as observableFrom } from 'rxjs';
import { delay, filter, takeWhile, tap } from 'rxjs/operators';
import { Position } from './../../common/core/graphics/position';
import { DejaMouseDragDropService, IDragCursorInfos, IDropCursorInfos } from './mouse-dragdrop.service';
 
@Component({
    encapsulation: ViewEncapsulation.None,
    selector: 'deja-mouse-dragdrop-cursor',
    styles: [
        require('./mouse-dragdrop-cursor.component.scss'),
    ],
    template: require('./mouse-dragdrop-cursor.component.html'),
})
export class DejaMouseDragDropCursorComponent implements OnDestroy {
    @ViewChild('block') private icon: ElementRef;
    @ViewChild('content') private content: ElementRef;
    private position$ = new BehaviorSubject<Position>(undefined);
    private cursor$ = new BehaviorSubject<IDragCursorInfos>(undefined);
    private _dragCursor: IDragCursorInfos;
    private _currentCursor: IDragCursorInfos;
    private _dropCursor: IDropCursorInfos;
    private isAlive = true;
 
    constructor(elementRef: ElementRef, private dragDropService: DejaMouseDragDropService) {
        const element = elementRef.nativeElement as HTMLElement;
 
        observableFrom(this.position$).pipe(
            takeWhile(() => this.isAlive))
            .subscribe((pos) => {
                element.style.left = pos ? `${pos.left}px` : '-1000px';
                element.style.top = pos ? `${pos.top}px` : '-1000px';
            });
 
        const cursor$ = observableFrom(this.cursor$);
 
        // Hide
        cursor$.pipe(
            takeWhile(() => this.isAlive),
            filter((dragCursor) => !dragCursor),
            tap((dragCursor) => {
                if (this._currentCursor && this.contentElement && this.iconElement) {
                    this.contentElement.style.opacity = '0';
                    this.iconElement.style.opacity = '0';
                }
                this._currentCursor = dragCursor;
            }),
            delay(300))
            .subscribe(() => {
                this.position$.next(null);
                element.style.display = 'none';
            });
 
        // Show
        cursor$.pipe(
            takeWhile(() => this.isAlive),
            filter((dragCursor) => !!dragCursor),
            tap((dragCursor) => {
                element.style.display = '';
                Eif (this.contentElement && this.iconElement) {
                    this.contentElement.style.opacity = '0';
                    this.iconElement.style.opacity = '0';
                }
                this._currentCursor = dragCursor;
            }),
            filter((dragCursor) => !dragCursor.className || dragCursor.className !== 'hidden'),
            tap((dragCursor) => {
                if (!!dragCursor.html) {
                    element.className = dragCursor.className;
                    Eif (this.contentElement && this.iconElement) {
                        this.contentElement.innerHTML = dragCursor.html;
                        this.contentElement.style.width = `${dragCursor.width || 48}px`;
                        this.contentElement.style.height = `${dragCursor.height || 48}px`;
                    }
                } else {
                    Eif (this.iconElement) {
                        this.iconElement.style.opacity = '1';
                    }
                }
            }),
            delay(1))
            .subscribe((dragCursor) => {
                if (!!dragCursor.html && this.contentElement) {
                    this.contentElement.style.opacity = '1';
                }
            });
 
        observableFrom(this.dragDropService.dragCursor$).pipe(
            takeWhile(() => this.isAlive))
            .subscribe((dragCursor) => {
                if (!!dragCursor !== !!this._dragCursor) {
                    this._dragCursor = dragCursor;
                }
 
                Iif (this._dropCursor && this._dragCursor) {
                    dragCursor.className = this._dropCursor.className || this._dragCursor.className;
                    dragCursor.html = this._dropCursor.html || this._dragCursor.html;
                    dragCursor.width = this._dropCursor.width || this._dragCursor.width;
                    dragCursor.height = this._dropCursor.height || this._dragCursor.height;
                }
 
                if (!!dragCursor !== !!this._currentCursor || (dragCursor && !!dragCursor.html !== !!this._currentCursor.html)) {
                    // Update Content
                    this.cursor$.next(dragCursor);
                } else Iif (dragCursor) {
                    // Update only Position
                    this.position$.next(dragCursor.position);
                }
            });
 
        observableFrom(this.dragDropService.dropCursor$).pipe(
            takeWhile(() => this.isAlive))
            .subscribe((dropCursor) => {
                this._dropCursor = dropCursor;
            });
    }
 
    private get iconElement() {
        return this.icon.nativeElement as HTMLElement;
    }
 
    private get contentElement() {
        return this.content.nativeElement as HTMLElement;
    }
 
    public ngOnDestroy() {
        this.isAlive = false;
    }
}