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

IgniteUI / igniteui-angular / 6309146873

26 Sep 2023 06:55AM CUT coverage: 92.235% (-0.02%) from 92.256%
6309146873

push

github

web-flow
fix(slider): properly adjusting bounds #13403 (#13472)

15302 of 17983 branches covered (0.0%)

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

26833 of 29092 relevant lines covered (92.23%)

29478.6 hits per line

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

87.32
/projects/igniteui-angular/src/lib/slider/thumb/thumb-slider.component.ts
1
import {
2
    Component,
3
    Input,
4
    HostListener,
5
    ElementRef,
6
    HostBinding,
7
    Output,
8
    EventEmitter,
9
    OnInit,
10
    OnDestroy,
11
    TemplateRef
12
} from '@angular/core';
2✔
13
import { takeUntil } from 'rxjs/operators';
14
import { SliderHandle } from '../slider.common';
791✔
15
import { Subject } from 'rxjs';
16
import { IgxDirectionality } from '../../services/direction/directionality';
17
import { NgClass } from '@angular/common';
791✔
18

19
/**
20
 * @hidden
791✔
21
 */
22
@Component({
23
    selector: 'igx-thumb',
791✔
24
    templateUrl: 'thumb-slider.component.html',
25
    standalone: true,
26
    imports: [NgClass]
791✔
27
})
28
export class IgxSliderThumbComponent implements OnInit, OnDestroy {
29
    @Input()
791✔
30
    public value: any;
31

32
    @Input()
1,552✔
33
    public continuous: boolean;
34

35
    @Input()
1,552✔
36
    public thumbLabelVisibilityDuration;
37

38
    @Input()
791✔
39
    public disabled: boolean;
40

41
    @Input()
42
    public onPan: Subject<number>;
43

44
    @Input()
368✔
45
    public stepDistance: number;
46

47
    @Input()
110✔
48
    public step: number;
49

50
    @Input()
8✔
51
    public templateRef: TemplateRef<any>;
8✔
52

8✔
53
    @Input()
54
    public context: any;
55

110✔
56
    @Input()
110✔
57
    public type: SliderHandle;
110✔
58

110✔
59
    @Input()
110✔
60
    public deactiveState: boolean;
110✔
61

110✔
62
    @Output()
110✔
63
    public thumbValueChange = new EventEmitter<number>();
110✔
64

110✔
65
    @Output()
110✔
66
    public thumbChange = new EventEmitter<any>();
110✔
67

68
    @Output()
69
    public hoverChange = new EventEmitter<boolean>();
×
70

×
71
    @HostBinding('attr.tabindex')
72
    public tabindex = 0;
73

×
74
    @HostBinding('attr.z-index')
75
    public zIndex = 0;
76

×
77
    @HostBinding('class.igx-slider-thumb-to--focused')
×
78
    public focused = false;
79

80
    @HostBinding('class.igx-slider-thumb-from')
37✔
81
    public get thumbFromClass() {
4✔
82
        return this.type === SliderHandle.FROM;
83
    }
33✔
84

33✔
85
    @HostBinding('class.igx-slider-thumb-to')
33✔
86
    public get thumbToClass() {
10✔
87
        return this.type === SliderHandle.TO;
88
    }
23✔
89

22✔
90
    @HostBinding('class.igx-slider-thumb-from--active')
91
    public get thumbFromActiveClass() {
92
        return this.type === SliderHandle.FROM && this._isActive;
1✔
93
    }
94

32✔
95
    @HostBinding('class.igx-slider-thumb-to--active')
32✔
96
    public get thumbToActiveClass() {
97
        return this.type === SliderHandle.TO && this._isActive;
98
    }
×
99

×
100
    @HostBinding('class.igx-slider-thumb-from--disabled')
×
101
    public get thumbFromDisabledClass() {
102
        return this.type === SliderHandle.FROM && this.disabled;
103
    }
7✔
104

7✔
105
    @HostBinding('class.igx-slider-thumb-to--disabled')
106
    public get thumbToDisabledClass() {
107
        return this.type === SliderHandle.TO && this.disabled;
108
    }
109

110
    @HostBinding('class.igx-slider-thumb-from--pressed')
110✔
111
    public get thumbFromPressedClass() {
112
        return this.type === SliderHandle.FROM && this.isActive && this._isPressed;
8✔
113
    }
114

115
    @HostBinding('class.igx-slider-thumb-to--pressed')
116
    public get thumbToPressedClass() {
117
        return this.type === SliderHandle.TO && this.isActive && this._isPressed;
118
    }
110✔
119

110✔
120
    public get getDotClass() {
121
        return {
122
            'igx-slider-thumb-from__dot': this.type === SliderHandle.FROM,
123
            'igx-slider-thumb-to__dot': this.type === SliderHandle.TO
124
        };
125
    }
56✔
126

127
    public isActive = false;
128

129
    public get nativeElement() {
130
        return this._elementRef.nativeElement;
131
    }
6✔
132

133
    public get destroy(): Subject<boolean> {
134
        return this._destroy$;
8✔
135
    }
8✔
136

5✔
137
    private _isActive = false;
138
    private _isPressed = false;
139
    private _destroy$ = new Subject<boolean>();
140

8!
141
    private get thumbPositionX() {
8✔
142
        const thumbBounderies = this.nativeElement.getBoundingClientRect();
143
        const thumbCenter = (thumbBounderies.right - thumbBounderies.left) / 2;
144
        return thumbBounderies.left + thumbCenter;
8✔
145
    }
8✔
146

1✔
147
    constructor(private _elementRef: ElementRef, private _dir: IgxDirectionality) { }
148

7✔
149
    @HostListener('pointerenter')
150
    public onPointerEnter() {
151
        this.focused = false;
7✔
152
        this.hoverChange.emit(true);
153
    }
154

62✔
155
    @HostListener('pointerleave')
62!
156
    public onPointerLeave() {
×
157
        this.hoverChange.emit(false);
158
    }
159

62✔
160
    @HostListener('keyup', ['$event'])
161
    public onKeyUp(event: KeyboardEvent) {
162
        event.stopPropagation();
2✔
163
        this.focused = true;
164
    }
165

166
    @HostListener('keydown', ['$event'])
2✔
167
    public onKeyDown(event: KeyboardEvent) {
168
        if (this.disabled) {
169
            return;
170
        }
171

172
        let increment = 0;
173
        const stepWithDir = (rtl: boolean) => rtl ? this.step * -1 : this.step;
174
        if (event.key.endsWith('Left')) {
175
            increment = stepWithDir(!this._dir.rtl);
176
        } else if (event.key.endsWith('Right')) {
177
            increment = stepWithDir(this._dir.rtl);
178
        } else {
179
            return;
180
        }
181

182
        this.thumbChange.emit();
183
        this.thumbValueChange.emit(increment);
184
    }
185

186
    @HostListener('blur')
187
    public onBlur() {
188
        this.isActive = false;
189
        this.zIndex = 0;
190
        this.focused = false;
191
    }
192

193
    @HostListener('focus')
194
    public onFocusListener() {
195
        this.isActive = true;
196
        this.zIndex = 1;
197
    }
198

199
    /**
200
     * @hidden
2✔
201
     */
202
    public ngOnInit() {
203
        this.onPan
204
            .pipe(takeUntil(this._destroy$))
205
            .subscribe(mouseX =>
206
                this.updateThumbValue(mouseX)
207
            );
208
    }
209

210
    /**
211
     * @hidden
212
     */
213
    public ngOnDestroy() {
214
        this._destroy$.next(true);
215
        this._destroy$.complete();
216
    }
217

218
    /**
219
     * Show thumb label and ripple.
220
     */
221
    public showThumbIndicators() {
222
        this.toggleThumbIndicators(true);
223
    }
224

225
    /**
226
     * Hide thumb label and ripple.
227
     */
228
    public hideThumbIndicators() {
229
        this.toggleThumbIndicators(false);
230
    }
231

232
    private updateThumbValue(mouseX: number) {
233
        const updateValue = this.calculateTrackUpdate(mouseX);
234
        if (this.isActive && updateValue !== 0) {
235
            this.thumbValueChange.emit(updateValue);
236
        }
237
    }
238

239
    private calculateTrackUpdate(mouseX: number): number {
240
        const scaleX = this._dir.rtl ? this.thumbPositionX - mouseX : mouseX - this.thumbPositionX;
241
        const stepDistanceCenter = this.stepDistance / 2;
242

243
        // If the thumb scale range (slider update) is less thàn a half step,
244
        // the position stays the same.
245
        const scaleXPositive = Math.abs(scaleX);
246
        if (scaleXPositive < stepDistanceCenter) {
247
            return 0;
248
        }
249

250
        return this.stepToProceed(scaleX, this.stepDistance);
251
    }
252

253
    private stepToProceed(scaleX, stepDist) {
254
        return Math.round(scaleX / stepDist) * this.step;
255
    }
256

257
    private toggleThumbIndicators(visible: boolean) {
258
        this._isPressed = visible;
259

260
        if (this.continuous || this.deactiveState) {
261
            this._isActive = false;
262
        } else {
263
            this._isActive = visible;
264
        }
265

266
    }
267
}
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