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

atinc / ngx-tethys / #55

30 Jul 2025 07:08AM UTC coverage: 9.866% (-80.4%) from 90.297%
#55

push

why520crazy
feat(empty): add setMessage for update display text #TINFR-2616

92 of 6794 branches covered (1.35%)

Branch coverage included in aggregate %.

2014 of 14552 relevant lines covered (13.84%)

6.15 hits per line

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

4.84
/src/core/scroll.ts
1
import { DOCUMENT } from '@angular/common';
2
import { Injectable, NgZone, inject } from '@angular/core';
3
import { reqAnimFrame } from './request-animation';
4

5
export type EasyingFn = (t: number, b: number, c: number, d: number) => number;
6

×
7
function easeInOutCubic(t: number, b: number, c: number, d: number): number {
×
8
    const cc = c - b;
×
9
    let tt = t / (d / 2);
×
10
    if (tt < 1) {
11
        return (cc / 2) * tt * tt * tt + b;
12
    } else {
×
13
        return (cc / 2) * ((tt -= 2) * tt * tt + 2) + b;
14
    }
15
}
1✔
16

17
@Injectable({
×
18
    providedIn: 'root'
×
19
})
×
20
export class ThyScrollService {
21
    private ngZone = inject(NgZone);
22

×
23
    private document: Document;
×
24

×
25
    constructor() {
×
26
        const document = inject(DOCUMENT);
27

28
        this.document = document;
×
29
    }
30

31
    /** Set the position of the scroll bar of `element`. */
32
    setScrollTop(element: Element | Window, topValue: number = 0): void {
×
33
        if (element === window) {
×
34
            this.document.body.scrollTop = topValue;
×
35
            this.document.documentElement.scrollTop = topValue;
×
36
        } else {
×
37
            (element as Element).scrollTop = topValue;
×
38
        }
×
39
    }
×
40

41
    /** Get the position of the scoll bar of `element`. */
×
42
    getScroll(element?: Element | Window, top: boolean = true): number {
43
        const target = element ? element : window;
44
        const prop = top ? 'pageYOffset' : 'pageXOffset';
45
        const method = top ? 'scrollTop' : 'scrollLeft';
46
        const isWindow = target === window;
47
        let ret = isWindow ? target[prop] : target[method];
48
        if (isWindow && typeof ret !== 'number') {
49
            ret = this.document.documentElement[method];
50
        }
51
        return ret;
×
52
    }
×
53

×
54
    /**
×
55
     * Scroll `element` to some position with animation.
×
56
     *
×
57
     * @param container container, `window` by default
×
58
     * @param topValue Scroll to `top`, 0 by default
×
59
     * @param easing Transition curve, `easeInOutCubic` by default
×
60
     * @param callback callback invoked when transition is done
×
61
     */
62
    scrollTo(container: Element | Window, topValue: number = 0, easing?: EasyingFn, callback?: () => void): void {
63
        const target = container ? container : window;
×
64
        const scrollTop = this.getScroll(target);
65
        const startTime = Date.now();
66
        const frameFunc = () => {
×
67
            const timestamp = Date.now();
68
            const time = timestamp - startTime;
69
            this.setScrollTop(target, (easing || easeInOutCubic)(time, scrollTop, topValue, 450));
70
            if (time < 450) {
71
                this.ngZone.runOutsideAngular(() => reqAnimFrame(frameFunc));
72
            } else {
×
73
                if (callback) {
74
                    // The `frameFunc` is called within the `<root>` zone, but we have to re-enter
1✔
75
                    // the Angular zone when calling custom callback to be backwards-compatible.
76
                    this.ngZone.run(() => callback());
1✔
77
                }
78
            }
79
        };
80
        // The `requestAnimationFrame` triggers change detection, but setting
81
        // `document.scrollTop` doesn't require Angular to run `ApplicationRef.tick()`.
82
        this.ngZone.runOutsideAngular(() => reqAnimFrame(frameFunc));
83
    }
84
}
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

© 2026 Coveralls, Inc