• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IgniteUI / igniteui-angular / 13527319862

pending completion
13527319862

Pull #14864

github

web-flow
Merge e6435f9b6 into bde20945a
Pull Request #14864: refactor(*): switch to control flow blocks

13329 of 15596 branches covered (85.46%)

26883 of 29333 relevant lines covered (91.65%)

33701.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

37.65
/projects/igniteui-angular/src/lib/grids/selection/drag-select.directive.ts
1
import { Directive, Input, Output, EventEmitter, ElementRef, OnDestroy, NgZone, OnInit, booleanAttribute } from '@angular/core';
2
import { interval, Observable, Subscription, Subject, animationFrameScheduler } from 'rxjs';
3
import { filter, takeUntil } from 'rxjs/operators';
4

5
enum DragScrollDirection {
2✔
6
    NONE,
2✔
7
    LEFT,
2✔
8
    TOP,
2✔
9
    RIGHT,
2✔
10
    BOTTOM,
2✔
11
    TOPLEFT,
2✔
12
    TOPRIGHT,
2✔
13
    BOTTOMLEFT,
2✔
14
    BOTTOMRIGHT
2✔
15
}
16

17
/**
18
 * An internal directive encapsulating the drag scroll behavior in the grid.
19
 *
20
 * @hidden @internal
21
 */
22
@Directive({
23
    selector: '[igxGridDragSelect]',
24
    standalone: true
25
})
26
export class IgxGridDragSelectDirective implements OnInit, OnDestroy {
2✔
27

28
    @Output()
29
    public dragStop = new EventEmitter<boolean>();
3,540✔
30

31
    @Output()
32
    public dragScroll = new EventEmitter<{ left: number; top: number }>();
3,540✔
33

34
    @Input({ alias: 'igxGridDragSelect', transform: booleanAttribute })
35
    public get activeDrag(): boolean {
36
        return this._activeDrag;
×
37
    }
38

39
    public set activeDrag(val: boolean) {
40
        if (val !== this._activeDrag) {
3,612✔
41
            this.unsubscribe();
3,612✔
42
            this._activeDrag = val;
3,612✔
43
        }
44
    }
45

46
    public get nativeElement() {
47
        return this.ref.nativeElement;
14,098✔
48
    }
49

50
    protected end$ = new Subject<any>();
3,540✔
51
    protected lastDirection = DragScrollDirection.NONE;
3,540✔
52
    protected _interval$: Observable<any>;
53
    protected _sub: Subscription;
54

55
    private _activeDrag: boolean;
56

57
    constructor(private ref: ElementRef<HTMLElement>, private zone: NgZone) {
3,540✔
58
        this._interval$ = interval(0, animationFrameScheduler).pipe(
3,540✔
59
            takeUntil(this.end$),
60
            filter(() => this.activeDrag)
×
61
        );
62
    }
63

64
    public ngOnInit() {
65
        this.zone.runOutsideAngular(() => {
3,540✔
66
            this.nativeElement.addEventListener('pointerover', this.startDragSelection);
3,540✔
67
            this.nativeElement.addEventListener('pointerleave', this.stopDragSelection);
3,540✔
68
        });
69
    }
70

71
    public ngOnDestroy() {
72
        this.zone.runOutsideAngular(() => {
3,509✔
73
            this.nativeElement.removeEventListener('pointerover', this.startDragSelection);
3,509✔
74
            this.nativeElement.removeEventListener('pointerleave', this.stopDragSelection);
3,509✔
75
        });
76
        this.unsubscribe();
3,509✔
77
        this.end$.complete();
3,509✔
78
    }
79

80

81
    protected startDragSelection = (ev: PointerEvent) => {
3,540✔
82
        if (!this.activeDrag) {
×
83
            return;
×
84
        }
85

86
        const x = ev.clientX;
×
87
        const y = ev.clientY;
×
88
        const { direction, delta } = this._measureDimensions(x, y);
×
89

90
        if (direction === this.lastDirection) {
×
91
            return;
×
92
        }
93

94
        this.unsubscribe();
×
95
        this._sub = this._interval$.subscribe(() => this.dragScroll.emit(delta));
×
96
        this.lastDirection = direction;
×
97
    };
98

99
    protected stopDragSelection = () => {
3,540✔
100
        if (!this.activeDrag) {
×
101
            return;
×
102
        }
103

104
        this.dragStop.emit(false);
×
105
        this.unsubscribe();
×
106
        this.lastDirection = DragScrollDirection.NONE;
×
107
    };
108

109
    protected _measureDimensions(x: number, y: number): { direction: DragScrollDirection; delta: { left: number; top: number } } {
110
        let direction: DragScrollDirection;
111
        let delta = { left: 0, top: 0 };
×
112
        const { left, top, width, height } = this.nativeElement.getBoundingClientRect();
×
113
        const RATIO = 0.15;
×
114

115
        const offsetX = Math.trunc(x - left);
×
116
        const offsetY = Math.trunc(y - top);
×
117

118
        const leftDirection = offsetX <= width * RATIO;
×
119
        const rightDirection = offsetX >= width * (1 - RATIO);
×
120
        const topDirection = offsetY <= height * RATIO;
×
121
        const bottomDirection = offsetY >= height * (1 - RATIO);
×
122

123
        if (topDirection && leftDirection) {
×
124
            direction = DragScrollDirection.TOPLEFT;
×
125
            delta = { left: -1, top: -1 };
×
126
        } else if (topDirection && rightDirection) {
×
127
            direction = DragScrollDirection.TOPRIGHT;
×
128
            delta = { left: 1, top: -1 };
×
129
        } else if (bottomDirection && leftDirection) {
×
130
            direction = DragScrollDirection.BOTTOMLEFT;
×
131
            delta = { left: -1, top: 1 };
×
132
        } else if (bottomDirection && rightDirection) {
×
133
            direction = DragScrollDirection.BOTTOMRIGHT;
×
134
            delta = { top: 1, left: 1 };
×
135
        } else if (topDirection) {
×
136
            direction = DragScrollDirection.TOP;
×
137
            delta.top = -1;
×
138
        } else if (bottomDirection) {
×
139
            direction = DragScrollDirection.BOTTOM;
×
140
            delta.top = 1;
×
141
        } else if (leftDirection) {
×
142
            direction = DragScrollDirection.LEFT;
×
143
            delta.left = -1;
×
144
        } else if (rightDirection) {
×
145
            direction = DragScrollDirection.RIGHT;
×
146
            delta.left = 1;
×
147
        } else {
148
            direction = DragScrollDirection.NONE;
×
149
        }
150

151
        return { direction, delta };
×
152

153
    }
154

155
    protected unsubscribe() {
156
        if (this._sub) {
7,121!
157
            this._sub.unsubscribe();
×
158
        }
159
    }
160
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc