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

IgniteUI / igniteui-angular / 13331632524

14 Feb 2025 02:51PM CUT coverage: 22.015% (-69.6%) from 91.622%
13331632524

Pull #15372

github

web-flow
Merge d52d57714 into bcb78ae0a
Pull Request #15372: chore(*): test ci passing

1990 of 15592 branches covered (12.76%)

431 of 964 new or added lines in 18 files covered. (44.71%)

19956 existing lines in 307 files now uncovered.

6452 of 29307 relevant lines covered (22.02%)

249.17 hits per line

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

21.28
/projects/igniteui-angular/src/lib/expansion-panel/toggle-animation-component.ts
1
import { AnimationReferenceMetadata } from '@angular/animations';
2
import { Directive, ElementRef, EventEmitter, Inject, OnDestroy } from '@angular/core';
3
import { noop, Subject } from 'rxjs';
4
import { takeUntil } from 'rxjs/operators';
5

6
import { IgxAngularAnimationService } from '../services/animation/angular-animation-service';
7
import { AnimationPlayer, AnimationService } from '../services/animation/animation';
8
import { growVerIn, growVerOut } from 'igniteui-angular/animations';
9

10
/**@hidden @internal */
11
export interface ToggleAnimationSettings {
12
    openAnimation: AnimationReferenceMetadata;
13
    closeAnimation: AnimationReferenceMetadata;
14
}
15

16
export interface ToggleAnimationOwner {
17
    animationSettings: ToggleAnimationSettings;
18
    openAnimationStart: EventEmitter<void>;
19
    openAnimationDone: EventEmitter<void>;
20
    closeAnimationStart: EventEmitter<void>;
21
    closeAnimationDone: EventEmitter<void>;
22
    openAnimationPlayer: AnimationPlayer;
23
    closeAnimationPlayer: AnimationPlayer;
24
    playOpenAnimation(element: ElementRef, onDone: () => void): void;
25
    playCloseAnimation(element: ElementRef, onDone: () => void): void;
26
}
27

28
/** @hidden @internal */
29
export enum ANIMATION_TYPE {
2✔
30
    OPEN = 'open',
2✔
31
    CLOSE = 'close',
2✔
32
}
33

34
/**@hidden @internal */
35
@Directive()
36
export abstract class ToggleAnimationPlayer implements ToggleAnimationOwner, OnDestroy {
2✔
37
    /** @hidden @internal */
38
    public openAnimationDone: EventEmitter<void> = new EventEmitter();
2✔
39
    /** @hidden @internal */
40
    public closeAnimationDone: EventEmitter<void> = new EventEmitter();
2✔
41
    /** @hidden @internal */
42
    public openAnimationStart: EventEmitter<void> = new EventEmitter();
2✔
43
    /** @hidden @internal */
44
    public closeAnimationStart: EventEmitter<void> = new EventEmitter();
2✔
45

46
    public get animationSettings(): ToggleAnimationSettings {
UNCOV
47
        return this._animationSettings;
×
48
    }
49
    public set animationSettings(value: ToggleAnimationSettings) {
UNCOV
50
        this._animationSettings = value;
×
51
    }
52

53
    /** @hidden @internal */
54
    public openAnimationPlayer: AnimationPlayer = null;
2✔
55

56
    /** @hidden @internal */
57
    public closeAnimationPlayer: AnimationPlayer = null;
2✔
58

59
    protected destroy$: Subject<void> = new Subject();
2✔
60
    protected players: Map<string, AnimationPlayer> = new Map();
2✔
61
    protected _animationSettings: ToggleAnimationSettings = {
2✔
62
        openAnimation: growVerIn,
63
        closeAnimation: growVerOut
64
    };
65

66
    private closeInterrupted = false;
2✔
67
    private openInterrupted = false;
2✔
68

69
    private _defaultClosedCallback = noop;
2✔
70
    private _defaultOpenedCallback = noop;
2✔
71
    private onClosedCallback: () => any = this._defaultClosedCallback;
2✔
72
    private onOpenedCallback: () => any = this._defaultOpenedCallback;
2✔
73

74
    constructor(@Inject(IgxAngularAnimationService) protected animationService: AnimationService) {
2✔
75
    }
76

77
    /** @hidden @internal */
78
    public playOpenAnimation(targetElement: ElementRef, onDone?: () => void): void {
UNCOV
79
        this.startPlayer(ANIMATION_TYPE.OPEN, targetElement, onDone || this._defaultOpenedCallback);
×
80
    }
81

82
    /** @hidden @internal */
83
    public playCloseAnimation(targetElement: ElementRef, onDone?: () => void): void {
UNCOV
84
        this.startPlayer(ANIMATION_TYPE.CLOSE, targetElement, onDone || this._defaultClosedCallback);
×
85
    }
86

87
    /** @hidden @internal */
88
    public ngOnDestroy() {
UNCOV
89
        this.destroy$.next();
×
UNCOV
90
        this.destroy$.complete();
×
91
    }
92

93
    private startPlayer(type: ANIMATION_TYPE, targetElement: ElementRef, callback: () => void): void {
UNCOV
94
        if (!targetElement) { // if no element is passed, there is nothing to animate
×
UNCOV
95
            return;
×
96
        }
UNCOV
97
        let target = this.getPlayer(type);
×
UNCOV
98
        if (!target) {
×
UNCOV
99
            target = this.initializePlayer(type, targetElement, callback);
×
100
        }
101
        // V.S. Jun 28th, 2021 #9783: player will NOT be initialized w/ null settings
102
        // events will already be emitted
UNCOV
103
        if (!target || target.hasStarted()) {
×
UNCOV
104
            return;
×
105
        }
UNCOV
106
        const targetEmitter = type === ANIMATION_TYPE.OPEN ? this.openAnimationStart : this.closeAnimationStart;
×
UNCOV
107
        targetEmitter.emit();
×
UNCOV
108
        if (target) {
×
UNCOV
109
            target.play();
×
110
        }
111
    }
112

113
    private initializePlayer(type: ANIMATION_TYPE, targetElement: ElementRef, callback: () => void): AnimationPlayer {
UNCOV
114
        const oppositeType = type === ANIMATION_TYPE.OPEN ? ANIMATION_TYPE.CLOSE : ANIMATION_TYPE.OPEN;
×
115
        // V.S. Jun 28th, 2021 #9783: Treat falsy animation settings as disabled animations
UNCOV
116
        const targetAnimationSettings = this.animationSettings || { closeAnimation: null, openAnimation: null };
×
UNCOV
117
        const animationSettings = type === ANIMATION_TYPE.OPEN ?
×
118
            targetAnimationSettings.openAnimation : targetAnimationSettings.closeAnimation;
119
        // V.S. Jun 28th, 2021 #9783: When no animation in target direction, emit start and done events and return
UNCOV
120
        if (!animationSettings) {
×
UNCOV
121
            this.setCallback(type, callback);
×
UNCOV
122
            const targetEmitter = type === ANIMATION_TYPE.OPEN ? this.openAnimationStart : this.closeAnimationStart;
×
UNCOV
123
            targetEmitter.emit();
×
UNCOV
124
            this.onDoneHandler(type);
×
UNCOV
125
            return;
×
126
        }
UNCOV
127
        const opposite = this.getPlayer(oppositeType);
×
UNCOV
128
        let oppositePosition = 1;
×
UNCOV
129
        if (opposite) {
×
UNCOV
130
            oppositePosition = opposite.position;
×
UNCOV
131
            this.cleanUpPlayer(oppositeType);
×
132
        }
UNCOV
133
        if (type === ANIMATION_TYPE.OPEN) {
×
UNCOV
134
            this.openAnimationPlayer = this.animationService.buildAnimation(animationSettings, targetElement.nativeElement);
×
UNCOV
135
        } else if (type === ANIMATION_TYPE.CLOSE) {
×
UNCOV
136
            this.closeAnimationPlayer = this.animationService.buildAnimation(animationSettings, targetElement.nativeElement);
×
137
        }
UNCOV
138
        const target = this.getPlayer(type);
×
UNCOV
139
        target.init();
×
UNCOV
140
        this.getPlayer(type).position = 1 - oppositePosition;
×
UNCOV
141
        this.setCallback(type, callback);
×
UNCOV
142
        target.animationEnd.pipe(takeUntil(this.destroy$)).subscribe(() => {
×
UNCOV
143
            this.onDoneHandler(type);
×
144
        });
UNCOV
145
        return target;
×
146
    }
147

148
    private onDoneHandler(type) {
UNCOV
149
        const targetEmitter = type === ANIMATION_TYPE.OPEN ? this.openAnimationDone : this.closeAnimationDone;
×
UNCOV
150
        const targetCallback = type === ANIMATION_TYPE.OPEN ? this.onOpenedCallback : this.onClosedCallback;
×
UNCOV
151
        targetCallback();
×
UNCOV
152
        if (!(type === ANIMATION_TYPE.OPEN ? this.openInterrupted : this.closeInterrupted)) {
×
UNCOV
153
            targetEmitter.emit();
×
154
        }
UNCOV
155
        this.cleanUpPlayer(type);
×
156
    }
157

158
    private setCallback(type: ANIMATION_TYPE, callback: () => void) {
UNCOV
159
        if (type === ANIMATION_TYPE.OPEN) {
×
UNCOV
160
            this.onOpenedCallback = callback;
×
UNCOV
161
            this.openInterrupted = false;
×
UNCOV
162
        } else if (type === ANIMATION_TYPE.CLOSE) {
×
UNCOV
163
            this.onClosedCallback = callback;
×
UNCOV
164
            this.closeInterrupted = false;
×
165
        }
166
    }
167

168
    private cleanUpPlayer(target: ANIMATION_TYPE) {
UNCOV
169
        switch (target) {
×
170
            case ANIMATION_TYPE.CLOSE:
UNCOV
171
                if (this.closeAnimationPlayer != null) {
×
UNCOV
172
                    this.closeAnimationPlayer.reset();
×
UNCOV
173
                    this.closeAnimationPlayer.destroy();
×
UNCOV
174
                    this.closeAnimationPlayer = null;
×
175
                }
UNCOV
176
                this.closeInterrupted = true;
×
UNCOV
177
                this.onClosedCallback = this._defaultClosedCallback;
×
UNCOV
178
                break;
×
179
            case ANIMATION_TYPE.OPEN:
UNCOV
180
                if (this.openAnimationPlayer != null) {
×
UNCOV
181
                    this.openAnimationPlayer.reset();
×
UNCOV
182
                    this.openAnimationPlayer.destroy();
×
UNCOV
183
                    this.openAnimationPlayer = null;
×
184
                }
UNCOV
185
                this.openInterrupted = true;
×
UNCOV
186
                this.onOpenedCallback = this._defaultOpenedCallback;
×
UNCOV
187
                break;
×
188
            default:
189
                break;
×
190
        }
191
    }
192

193
    private getPlayer(type: ANIMATION_TYPE): AnimationPlayer {
UNCOV
194
        switch (type) {
×
195
            case ANIMATION_TYPE.OPEN:
UNCOV
196
                return this.openAnimationPlayer;
×
197
            case ANIMATION_TYPE.CLOSE:
UNCOV
198
                return this.closeAnimationPlayer;
×
199
            default:
200
                return null;
×
201
        }
202
    }
203
}
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