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

atinc / ngx-tethys / d9ae709b-3c27-4b69-b125-b8b80b54f90b

pending completion
d9ae709b-3c27-4b69-b125-b8b80b54f90b

Pull #2757

circleci

mengshuicmq
fix: fix code review
Pull Request #2757: feat(color-picker): color-picker support disabled (#INFR-8645)

98 of 6315 branches covered (1.55%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

2392 of 13661 relevant lines covered (17.51%)

83.12 hits per line

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

0.63
/src/drag-drop/drag-ref.ts
1
import { NgZone, ElementRef, Renderer2 } from '@angular/core';
2
import { coerceElement } from '@angular/cdk/coercion';
3
import { Subject, fromEvent } from 'rxjs';
4
import { auditTime, takeUntil } from 'rxjs/operators';
5
import { ThyDragHandleDirective } from './drag-handle.directive';
6
import { ThyDragDropService } from './drag-drop.service';
1✔
7
import { ThyDragStartEvent, ThyDragEndEvent, ThyDragOverEvent, ThyDragDropEvent, ThyDropPosition } from './drag-drop.class';
8
import { ThyDragDirective } from './drag.directive';
9
import { IThyDropContainerDirective } from './drop-container.class';
10
import { coerceArray, isEmpty, isString } from 'ngx-tethys/util';
11

12
const dropPositionClass = {
13
    [ThyDropPosition.in]: 'thy-drop-position-in',
×
14
    [ThyDropPosition.before]: 'thy-drop-position-before',
15
    [ThyDropPosition.after]: 'thy-drop-position-after'
16
};
×
17

18
export class DragRef<T = any> {
19
    private rootElement: HTMLElement;
×
20

×
21
    private contentElement: HTMLElement;
×
22

×
23
    private target: HTMLElement;
×
24

×
25
    private handles: ThyDragHandleDirective[];
×
26

×
27
    private ngUnsubscribe$ = new Subject();
×
28

×
29
    started = new Subject<ThyDragStartEvent>();
×
30

×
31
    ended = new Subject<ThyDragEndEvent>();
×
32

×
33
    overed = new Subject<ThyDragOverEvent>();
×
34

×
35
    dropped = new Subject<ThyDragDropEvent>();
×
36

37
    entered = new Subject<DragEvent>();
38

×
39
    leaved = new Subject<DragEvent>();
×
40

×
41
    private _disabled = false;
×
42

43
    get disabled(): boolean {
44
        return (this.container && this.container.disabled) || this._disabled;
45
    }
×
46
    set disabled(value: boolean) {
×
47
        this._disabled = value;
×
48
    }
×
49

50
    private addPositionClass$ = new Subject<{ element: HTMLElement; class: string }>();
51

×
52
    constructor(
×
53
        element: ElementRef<HTMLElement> | HTMLElement,
54
        private drag: ThyDragDirective,
55
        private container: IThyDropContainerDirective<T>,
×
56
        private dragDropService: ThyDragDropService<T>,
×
57
        private document: any,
58
        private ngZone: NgZone,
59
        private renderer: Renderer2
×
60
    ) {
61
        this.withRootElement(element);
62
        this.subAddPositionClass();
63
    }
64

65
    subAddPositionClass() {
66
        this.addPositionClass$.pipe(auditTime(30), takeUntil(this.ngUnsubscribe$)).subscribe(data => {
×
67
            this.removeExistClassByMap(this.dragDropService.classMap);
68
            this.dragDropService.classMap.set(data.element, data.class);
69
            this.renderer.addClass(data.element, data.class);
×
70
        });
71
    }
72

×
73
    withRootElement(rootElement: ElementRef<HTMLElement> | HTMLElement): this {
×
74
        const element = coerceElement(rootElement);
×
75
        this.rootElement = element;
×
76
        this.registerDragDropEvents();
77
        return this;
78
    }
79

80
    withContentElement(contentElement: ElementRef<HTMLElement> | HTMLElement): this {
81
        this.contentElement = coerceElement(contentElement);
×
82
        return this;
×
83
    }
84

85
    withHandles(handleOrHandles: ThyDragHandleDirective | ThyDragHandleDirective[]): this {
86
        this.handles = coerceArray(handleOrHandles);
87
        return this;
88
    }
×
89

×
90
    private registerDragDropEvents() {
×
91
        const events = {
92
            dragstart: this.dragStart,
×
93
            dragover: this.dragOver,
×
94
            dragend: this.dragEnd,
×
95
            drop: this.dragDrop,
96
            dragleave: this.dragLeave,
97
            dragenter: (event: DragEvent) => {
98
                this.entered.next(event);
×
99
            },
×
100
            mouseover: (event: MouseEvent) => {
×
101
                this.target = event.target as HTMLElement;
102
            }
×
103
        };
104
        this.ngZone.runOutsideAngular(() => {
105
            for (const name in events) {
×
106
                if (events.hasOwnProperty(name)) {
107
                    fromEvent(this.rootElement, name).pipe(takeUntil(this.ngUnsubscribe$)).subscribe(events[name].bind(this));
108
                }
109
            }
×
110
        });
×
111
    }
×
112

113
    private dragStart(event: DragEvent) {
114
        event.stopPropagation();
×
115
        const dragStartEvent: ThyDragStartEvent = {
116
            event: event,
117
            item: this.drag.data,
118
            containerItems: this.container.data,
×
119
            currentIndex: this.container.data.indexOf(this.drag.data)
×
120
        };
121
        if (this.disabled || !this.isTriggerHandle() || (this.container.beforeStart && !this.container.beforeStart(dragStartEvent))) {
×
122
            event.preventDefault();
×
123
            return false;
124
        }
×
125
        this.dragDropService.previousDrag = this.drag;
126
        this.ngZone.run(() => {
127
            this.started.next(dragStartEvent);
×
128
        });
×
129
    }
×
130

×
131
    private isTriggerHandle() {
×
132
        if (this.handles && this.handles.length > 0) {
×
133
            const targetHandle = this.handles.find(handle => {
134
                return (
×
135
                    !handle.disabled && (handle.element.nativeElement === this.target || handle.element.nativeElement.contains(this.target))
136
                );
137
            });
138
            return !!targetHandle;
139
        } else {
140
            return true;
141
        }
142
    }
×
143

×
144
    private getPreviousEventData() {
×
145
        const previousItem = this.dragDropService.previousDrag?.data;
146
        const previousContainerItems = this.dragDropService.previousDrag?.container?.data;
147
        return {
148
            previousItem: previousItem,
×
149
            previousContainerItems,
×
150
            previousIndex: isEmpty(previousContainerItems) ? -1 : previousContainerItems.indexOf(previousItem)
×
151
        };
152
    }
153

×
154
    private isContinueDragOver(event: ThyDragOverEvent, container: IThyDropContainerDirective<T>) {
×
155
        if (event.item === event.previousItem && event.position === ThyDropPosition.in) {
×
156
            return false;
×
157
        }
×
158
        if (container && container.beforeOver) {
159
            return container.beforeOver(event);
×
160
        }
161
        return true;
162
    }
163

164
    private dragOver(event: DragEvent) {
165
        event.stopPropagation();
166
        event.preventDefault();
167

×
168
        const dropPosition = this.calcDropPosition(event);
×
169
        const previousEventData = this.getPreviousEventData();
×
170
        if (previousEventData.previousIndex < 0) {
171
            return;
×
172
        }
×
173
        const dragOverEvent: ThyDragOverEvent<T> = {
174
            event: event,
175
            item: this.drag.data,
176
            containerItems: this.drag.container.data,
×
177
            currentIndex: this.container.data.indexOf(this.drag.data),
×
178
            position: dropPosition,
×
179
            ...previousEventData
180
        };
181

182
        if (this.isContinueDragOver(dragOverEvent, this.container)) {
183
            this.dragOverHandler(dropPosition);
184
            this.overed.next(dragOverEvent);
×
185
        }
186
    }
187

×
188
    private dragOverHandler(position: ThyDropPosition) {
×
189
        const element = this.contentElement || this.rootElement;
×
190
        this.addPositionClass$.next({ element, class: dropPositionClass[position] });
191
        this.dragDropService.dropPosition = position;
192
    }
×
193

×
194
    private dragDrop(event: DragEvent) {
×
195
        event.stopPropagation();
×
196
        this.clearDragPositionClass();
197
        const previousEventData = this.getPreviousEventData();
198
        if (previousEventData.previousIndex < 0) {
199
            return;
×
200
        }
×
201
        const dragDropEvent: ThyDragDropEvent<T> = {
×
202
            event: event,
203
            item: this.drag.data,
204
            containerItems: this.drag.container.data,
205
            currentIndex: this.container.data.indexOf(this.drag.data),
206
            position: this.calcDropPosition(event),
×
207
            ...previousEventData
×
208
        };
×
209
        if (this.dragDropService.previousDrag === this.drag || (this.container.beforeDrop && !this.container.beforeDrop(dragDropEvent))) {
×
210
            event.preventDefault();
211
            return;
212
        }
×
213
        this.ngZone.run(() => {
×
214
            this.dropped.next(dragDropEvent);
×
215
        });
216
    }
×
217

×
218
    private dragEnd(event: DragEvent) {
219
        this.clearDragPositionClass();
×
220
        this.ngZone.run(() => {
221
            this.ended.next({
222
                event: event,
×
223
                item: this.drag.data,
224
                containerItems: this.container.data
225
            });
226
        });
227
        this.dragDropService.previousDrag = undefined;
228
    }
229

230
    private dragLeave(event: DragEvent) {
231
        event.stopPropagation();
232
        this.clearDragPositionClass();
233
        this.leaved.next(event);
234
    }
235

236
    private clearDragPositionClass() {
237
        setTimeout(() => {
238
            const classMap = this.dragDropService.classMap;
239
            this.removeExistClassByMap(classMap);
240
            classMap.clear();
241
        }, 30);
242
    }
243

244
    private removeExistClassByMap(classMap: Map<Element, string>) {
245
        classMap.forEach((value, key) => {
246
            if (isString(value) && key) {
247
                this.renderer.removeClass(key, value);
248
            }
249
        });
250
    }
251

252
    private calcDropPosition(event: DragEvent): ThyDropPosition {
253
        const sideRange = 0.25;
254
        const minGap = 2;
255
        const { clientY } = event;
256
        const { top, bottom, height } = event.srcElement
257
            ? (event.srcElement as Element).getBoundingClientRect()
258
            : (event.target as Element).getBoundingClientRect();
259
        const des = Math.max(height * sideRange, minGap);
260
        if (clientY <= top + des) {
261
            return ThyDropPosition.before;
262
        } else if (clientY >= bottom - des) {
263
            return ThyDropPosition.after;
264
        }
265
        return ThyDropPosition.in;
266
    }
267

268
    dispose() {
269
        this.ngUnsubscribe$.complete();
270
    }
271
}
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