• 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

39.42
/projects/igniteui-angular/src/lib/time-picker/time-picker.directives.ts
1
/**
2
 * This file contains all the directives used by the @link IgxTimePickerComponent.
3
 * You should generally not use them directly.
4
 *
5
 * @preferred
6
 */
7
import {
8
    Directive,
9
    ElementRef,
10
    HostBinding,
11
    HostListener,
12
    Inject,
13
    Input,
14
    OnDestroy,
15
    OnInit
16
} from '@angular/core';
17
import { HammerGesturesManager } from '../core/touch';
18
import { DateTimeUtil } from '../date-common/util/date-time.util';
19
import { IgxTimePickerBase, IGX_TIME_PICKER_COMPONENT } from './time-picker.common';
20
import { HammerInput, HammerOptions } from '../core/touch-annotations';
21

22
/** @hidden */
23
@Directive({
24
    selector: '[igxItemList]',
25
    providers: [HammerGesturesManager],
26
    standalone: true
27
})
28
export class IgxItemListDirective implements OnInit, OnDestroy {
2✔
29
    @HostBinding('attr.tabindex')
30
    public tabindex = 0;
4✔
31

32
    @Input('igxItemList')
33
    public type: string;
34

35
    public isActive: boolean;
36

37
    constructor(
38
        @Inject(IGX_TIME_PICKER_COMPONENT) public timePicker: IgxTimePickerBase,
4✔
39
        private elementRef: ElementRef,
4✔
40
        private touchManager: HammerGesturesManager
4✔
41
    ) { }
42

43
    @HostBinding('class.igx-time-picker__column')
44
    public get defaultCSS(): boolean {
45
        return true;
40✔
46
    }
47

48
    @HostBinding('class.igx-time-picker__hourList')
49
    public get hourCSS(): boolean {
50
        return this.type === 'hourList';
40✔
51
    }
52

53
    @HostBinding('class.igx-time-picker__minuteList')
54
    public get minuteCSS(): boolean {
55
        return this.type === 'minuteList';
40✔
56
    }
57

58
    @HostBinding('class.igx-time-picker__secondsList')
59
    public get secondsCSS(): boolean {
60
        return this.type === 'secondsList';
40✔
61
    }
62

63
    @HostBinding('class.igx-time-picker__ampmList')
64
    public get ampmCSS(): boolean {
65
        return this.type === 'ampmList';
40✔
66
    }
67

68
    @HostListener('focus')
69
    public onFocus() {
UNCOV
70
        this.isActive = true;
×
71
    }
72

73
    @HostListener('blur')
74
    public onBlur() {
UNCOV
75
        this.isActive = false;
×
76
    }
77

78
    /**
79
     * @hidden
80
     */
81
    @HostListener('keydown.arrowdown', ['$event'])
82
    public onKeydownArrowDown(event: KeyboardEvent) {
UNCOV
83
        event.preventDefault();
×
84

UNCOV
85
        this.nextItem(1);
×
86
    }
87

88
    /**
89
     * @hidden
90
     */
91
    @HostListener('keydown.arrowup', ['$event'])
92
    public onKeydownArrowUp(event: KeyboardEvent) {
UNCOV
93
        event.preventDefault();
×
94

UNCOV
95
        this.nextItem(-1);
×
96
    }
97

98
    /**
99
     * @hidden
100
     */
101
    @HostListener('keydown.arrowright', ['$event'])
102
    public onKeydownArrowRight(event: KeyboardEvent) {
UNCOV
103
        event.preventDefault();
×
104

UNCOV
105
        const listName = (event.target as HTMLElement).className;
×
106

UNCOV
107
        if (listName.indexOf('hourList') !== -1 && this.timePicker.minuteList) {
×
UNCOV
108
            this.timePicker.minuteList.nativeElement.focus();
×
UNCOV
109
        } else if ((listName.indexOf('hourList') !== -1 || listName.indexOf('minuteList') !== -1) && this.timePicker.secondsList) {
×
110
            this.timePicker.secondsList.nativeElement.focus();
×
UNCOV
111
        } else if ((listName.indexOf('hourList') !== -1 || listName.indexOf('minuteList') !== -1 ||
×
112
            listName.indexOf('secondsList') !== -1) && this.timePicker.ampmList) {
UNCOV
113
            this.timePicker.ampmList.nativeElement.focus();
×
114
        }
115
    }
116

117
    /**
118
     * @hidden
119
     */
120
    @HostListener('keydown.arrowleft', ['$event'])
121
    public onKeydownArrowLeft(event: KeyboardEvent) {
UNCOV
122
        event.preventDefault();
×
UNCOV
123
        const listName = (event.target as HTMLElement).className;
×
124

UNCOV
125
        if (listName.indexOf('ampmList') !== -1 && this.timePicker.secondsList) {
×
126
            this.timePicker.secondsList.nativeElement.focus();
×
UNCOV
127
        } else if (listName.indexOf('secondsList') !== -1 && this.timePicker.secondsList
×
128
            && listName.indexOf('minutesList') && this.timePicker.minuteList) {
129
            this.timePicker.minuteList.nativeElement.focus();
×
UNCOV
130
        } else if (listName.indexOf('ampmList') !== -1 && this.timePicker.minuteList) {
×
UNCOV
131
            this.timePicker.minuteList.nativeElement.focus();
×
UNCOV
132
        } else if ((listName.indexOf('ampmList') !== -1 || listName.indexOf('secondsList') !== -1 ||
×
133
            listName.indexOf('minuteList') !== -1) && this.timePicker.hourList) {
UNCOV
134
            this.timePicker.hourList.nativeElement.focus();
×
135
        }
136
    }
137

138
    /**
139
     * @hidden
140
     */
141
    @HostListener('keydown.enter', ['$event'])
142
    public onKeydownEnter(event: KeyboardEvent) {
UNCOV
143
        event.preventDefault();
×
UNCOV
144
        this.timePicker.okButtonClick();
×
145
    }
146

147
    /**
148
     * @hidden
149
     */
150
    @HostListener('keydown.escape', ['$event'])
151
    public onKeydownEscape(event: KeyboardEvent) {
152
        event.preventDefault();
×
153

154
        this.timePicker.cancelButtonClick();
×
155
    }
156

157
    /**
158
     * @hidden
159
     */
160
    @HostListener('mouseover')
161
    public onHover() {
162
        this.elementRef.nativeElement.focus();
×
163
    }
164

165
    /**
166
     * @hidden
167
     */
168
    @HostListener('wheel', ['$event'])
169
    public onScroll(event) {
UNCOV
170
        event.preventDefault();
×
UNCOV
171
        event.stopPropagation();
×
172

UNCOV
173
        const delta = event.deltaY;
×
UNCOV
174
        if (delta !== 0) {
×
UNCOV
175
            this.nextItem(delta);
×
176
        }
177
    }
178

179
    /**
180
     * @hidden @internal
181
     */
182
    public ngOnInit() {
183
        const hammerOptions: HammerOptions = { recognizers: [[HammerGesturesManager.Hammer?.Pan, { direction: HammerGesturesManager.Hammer?.DIRECTION_VERTICAL, threshold: 10 }]] };
4✔
184
        this.touchManager.addEventListener(this.elementRef.nativeElement, 'pan', this.onPanMove, hammerOptions);
4✔
185
    }
186

187
    /**
188
     * @hidden @internal
189
     */
190
     public ngOnDestroy() {
191
        this.touchManager.destroy();
4✔
192
    }
193

194
    private onPanMove = (event: HammerInput) => {
4✔
UNCOV
195
        const delta = event.deltaY < 0 ? -1 : event.deltaY > 0 ? 1 : 0;
×
UNCOV
196
        if (delta !== 0) {
×
197
            this.nextItem(delta);
×
198
        }
199
    };
200

201
    private nextItem(delta: number): void {
UNCOV
202
        switch (this.type) {
×
203
            case 'hourList': {
UNCOV
204
                this.timePicker.nextHour(delta);
×
UNCOV
205
                break;
×
206
            }
207
            case 'minuteList': {
UNCOV
208
                this.timePicker.nextMinute(delta);
×
UNCOV
209
                break;
×
210
            }
211
            case 'secondsList': {
UNCOV
212
                this.timePicker.nextSeconds(delta);
×
UNCOV
213
                break;
×
214
            }
215
            case 'ampmList': {
UNCOV
216
                this.timePicker.nextAmPm(delta);
×
UNCOV
217
                break;
×
218
            }
219
        }
220
    }
221
}
222

223
/**
224
 * @hidden
225
 */
226
@Directive({
227
    selector: '[igxTimeItem]',
228
    exportAs: 'timeItem',
229
    standalone: true
230
})
231
export class IgxTimeItemDirective {
2✔
232
    @Input('igxTimeItem')
233
    public value: string;
234

235
    @HostBinding('class.igx-time-picker__item')
236
    public get defaultCSS(): boolean {
237
        return true;
280✔
238
    }
239

240
    @HostBinding('class.igx-time-picker__item--selected')
241
    public get selectedCSS(): boolean {
242
        return this.isSelectedTime;
280✔
243
    }
244

245
    @HostBinding('class.igx-time-picker__item--active')
246
    public get activeCSS(): boolean {
247
        return this.isSelectedTime && this.itemList.isActive;
280✔
248
    }
249

250
    public get isSelectedTime(): boolean {
251
        const currentValue = this.value.length < 2 ? `0${this.value}` : this.value;
1,680!
252
        const dateType = this.itemList.type;
1,680✔
253
        const inputDateParts = DateTimeUtil.parseDateTimeFormat(this.timePicker.appliedFormat);
1,680✔
254
        switch (dateType) {
1,680!
255
            case 'hourList':
256
                const hourPart = inputDateParts.find(element => element.type === 'hours');
840✔
257
                return DateTimeUtil.getPartValue(this.timePicker.selectedDate, hourPart, hourPart.format.length) === currentValue;
840✔
258
            case 'minuteList':
259
                const minutePart = inputDateParts.find(element => element.type === 'minutes');
2,520✔
260
                return DateTimeUtil.getPartValue(this.timePicker.selectedDate, minutePart, minutePart.format.length) === currentValue;
840✔
261
            case 'secondsList':
UNCOV
262
                const secondsPart = inputDateParts.find(element => element.type === 'seconds');
×
UNCOV
263
                return DateTimeUtil.getPartValue(this.timePicker.selectedDate, secondsPart, secondsPart.format.length) === currentValue;
×
264
            case 'ampmList':
UNCOV
265
                const ampmPart = inputDateParts.find(element => element.format.indexOf('a') !== -1 || element.format === 'tt');
×
UNCOV
266
                return DateTimeUtil.getPartValue(this.timePicker.selectedDate, ampmPart, ampmPart.format.length) === this.value;
×
267
        }
268
    }
269

270
    public get minValue(): string {
271
        const dateType = this.itemList.type;
40✔
272
        const inputDateParts = DateTimeUtil.parseDateTimeFormat(this.timePicker.appliedFormat);
40✔
273
        switch (dateType) {
40!
274
            case 'hourList':
275
                return this.getHourPart(this.timePicker.minDropdownValue);
20✔
276
            case 'minuteList':
277
                if (this.timePicker.selectedDate.getHours() === this.timePicker.minDropdownValue.getHours()) {
20✔
278
                    const minutePart = inputDateParts.find(element => element.type === 'minutes');
60✔
279
                    return DateTimeUtil.getPartValue(this.timePicker.minDropdownValue, minutePart, minutePart.format.length);
20✔
280
                }
UNCOV
281
                return '00';
×
282
            case 'secondsList':
UNCOV
283
                const date = new Date(this.timePicker.selectedDate);
×
UNCOV
284
                const min = new Date(this.timePicker.minDropdownValue);
×
UNCOV
285
                date.setSeconds(0);
×
UNCOV
286
                min.setSeconds(0);
×
UNCOV
287
                if (date.getTime() === min.getTime()) {
×
288
                    const secondsPart = inputDateParts.find(element => element.type === 'seconds');
×
289
                    return DateTimeUtil.getPartValue(this.timePicker.minDropdownValue, secondsPart, secondsPart.format.length);
×
290
                }
UNCOV
291
                return '00';
×
292
            case 'ampmList':
UNCOV
293
                const ampmPart = inputDateParts.find(element => element.format.indexOf('a') !== -1 || element.format === 'tt');
×
UNCOV
294
                return DateTimeUtil.getPartValue(this.timePicker.minDropdownValue, ampmPart, ampmPart.format.length);
×
295
        }
296
    }
297

298
    public get maxValue(): string {
299
        const dateType = this.itemList.type;
40✔
300
        const inputDateParts = DateTimeUtil.parseDateTimeFormat(this.timePicker.appliedFormat);
40✔
301
        switch (dateType) {
40!
302
            case 'hourList':
303
                return this.getHourPart(this.timePicker.maxDropdownValue);
20✔
304
            case 'minuteList':
305
                if (this.timePicker.selectedDate.getHours() === this.timePicker.maxDropdownValue.getHours()) {
20!
UNCOV
306
                    const minutePart = inputDateParts.find(element => element.type === 'minutes');
×
UNCOV
307
                    return DateTimeUtil.getPartValue(this.timePicker.maxDropdownValue, minutePart, minutePart.format.length);
×
308
                } else {
309
                    const currentTime = new Date(this.timePicker.selectedDate);
20✔
310
                    const minDelta = this.timePicker.itemsDelta.minutes;
20✔
311
                    const remainder = 60 % minDelta;
20✔
312
                    const delta = remainder === 0 ? 60 - minDelta : 60 - remainder;
20!
313
                    currentTime.setMinutes(delta);
20✔
314
                    const minutePart = inputDateParts.find(element => element.type === 'minutes');
60✔
315
                    return DateTimeUtil.getPartValue(currentTime, minutePart, minutePart.format.length);
20✔
316
                }
317
            case 'secondsList':
UNCOV
318
                const date = new Date(this.timePicker.selectedDate);
×
UNCOV
319
                const max = new Date(this.timePicker.maxDropdownValue);
×
UNCOV
320
                date.setSeconds(0);
×
UNCOV
321
                max.setSeconds(0);
×
UNCOV
322
                if (date.getTime() === max.getTime()) {
×
323
                    const secondsPart = inputDateParts.find(element => element.type === 'seconds');
×
324
                    return DateTimeUtil.getPartValue(this.timePicker.maxDropdownValue, secondsPart, secondsPart.format.length);
×
325
                } else {
UNCOV
326
                    const secDelta = this.timePicker.itemsDelta.seconds;
×
UNCOV
327
                    const remainder = 60 % secDelta;
×
UNCOV
328
                    const delta = remainder === 0 ? 60 - secDelta : 60 - remainder;
×
UNCOV
329
                    date.setSeconds(delta);
×
UNCOV
330
                    const secondsPart = inputDateParts.find(element => element.type === 'seconds');
×
UNCOV
331
                    return DateTimeUtil.getPartValue(date, secondsPart, secondsPart.format.length);
×
332
                }
333
            case 'ampmList':
UNCOV
334
                const ampmPart = inputDateParts.find(element => element.format.indexOf('a') !== -1 || element.format === 'tt');
×
UNCOV
335
                return DateTimeUtil.getPartValue(this.timePicker.maxDropdownValue, ampmPart, ampmPart.format.length);
×
336
        }
337
    }
338

339
    public get hourValue(): string {
340
        return this.getHourPart(this.timePicker.selectedDate);
20✔
341
    }
342

343
    constructor(@Inject(IGX_TIME_PICKER_COMPONENT)
344
    public timePicker: IgxTimePickerBase,
28✔
345
        private itemList: IgxItemListDirective) { }
28✔
346

347
    @HostListener('click', ['value'])
348
    public onClick(item) {
UNCOV
349
        if (item !== '') {
×
UNCOV
350
            const dateType = this.itemList.type;
×
UNCOV
351
            this.timePicker.onItemClick(item, dateType);
×
352
        }
353
    }
354

355
    private getHourPart(date: Date): string {
356
        const inputDateParts = DateTimeUtil.parseDateTimeFormat(this.timePicker.appliedFormat);
60✔
357
        const hourPart = inputDateParts.find(element => element.type === 'hours');
60✔
358
        const ampmPart = inputDateParts.find(element =>element.format.indexOf('a') !== -1 || element.format === 'tt');
180✔
359
        const hour = DateTimeUtil.getPartValue(date, hourPart, hourPart.format.length);
60✔
360
        if (ampmPart) {
60!
UNCOV
361
            const ampm = DateTimeUtil.getPartValue(date, ampmPart, ampmPart.format.length);
×
UNCOV
362
            return `${hour} ${ampm}`;
×
363
        }
364
        return hour;
60✔
365
    }
366
}
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