@imihai/angular-datetime-picker 22.0.8 → 22.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Input, Directive, InjectionToken, inject, LOCALE_ID, Optional, Inject, Injectable, EventEmitter, Output, ChangeDetectionStrategy, Component, ViewChild, signal, TemplateRef,
|
|
2
|
+
import { Input, Directive, InjectionToken, inject, LOCALE_ID, Optional, Inject, Injectable, Injector, DestroyRef, EventEmitter, afterNextRender, Output, ChangeDetectionStrategy, Component, ViewChild, signal, TemplateRef, SkipSelf, untracked, forwardRef, Pipe, NgModule } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/common';
|
|
4
4
|
import { getLocaleFirstDayOfWeek, DOCUMENT, CommonModule } from '@angular/common';
|
|
5
5
|
import * as i1 from '@angular/cdk/a11y';
|
|
6
6
|
import { A11yModule } from '@angular/cdk/a11y';
|
|
7
7
|
import * as i1$1 from '@angular/cdk/overlay';
|
|
8
8
|
import { NoopScrollStrategy, Overlay, OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
|
|
9
|
-
import {
|
|
9
|
+
import { coerceBooleanProperty, coerceNumberProperty, coerceArray } from '@angular/cdk/coercion';
|
|
10
|
+
import { Subscription, EMPTY, merge, Subject, filter, take, defer } from 'rxjs';
|
|
10
11
|
import * as i2$1 from '@angular/cdk/portal';
|
|
11
12
|
import { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, PortalModule } from '@angular/cdk/portal';
|
|
12
13
|
import { ENTER, PAGE_DOWN, PAGE_UP, END, HOME, DOWN_ARROW, UP_ARROW, RIGHT_ARROW, LEFT_ARROW, SPACE, ESCAPE } from '@angular/cdk/keycodes';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
14
|
+
import { debounceTime, startWith, take as take$1, filter as filter$1 } from 'rxjs/operators';
|
|
15
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
15
16
|
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators } from '@angular/forms';
|
|
16
|
-
import { Settings,
|
|
17
|
+
import { Settings, DateTime, Info } from 'luxon';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* date-time-picker-trigger.directive
|
|
20
21
|
*/
|
|
21
22
|
class OwlDateTimeTriggerDirective {
|
|
22
23
|
get disabled() {
|
|
23
|
-
return this._disabled === undefined ? this.dtPicker
|
|
24
|
+
return this._disabled === undefined ? !!this.dtPicker?.disabled : !!this._disabled;
|
|
24
25
|
}
|
|
25
26
|
set disabled(value) {
|
|
26
|
-
this._disabled = value;
|
|
27
|
+
this._disabled = coerceBooleanProperty(value);
|
|
27
28
|
}
|
|
28
29
|
get owlDTTriggerDisabledClass() {
|
|
29
30
|
return this.disabled;
|
|
@@ -35,7 +36,7 @@ class OwlDateTimeTriggerDirective {
|
|
|
35
36
|
ngOnInit() {
|
|
36
37
|
}
|
|
37
38
|
ngOnChanges(changes) {
|
|
38
|
-
if (changes.
|
|
39
|
+
if (changes.dtPicker) {
|
|
39
40
|
this.watchStateChanges();
|
|
40
41
|
}
|
|
41
42
|
}
|
|
@@ -46,7 +47,7 @@ class OwlDateTimeTriggerDirective {
|
|
|
46
47
|
this.stateChanges.unsubscribe();
|
|
47
48
|
}
|
|
48
49
|
handleClickOnHost(event) {
|
|
49
|
-
if (this.dtPicker) {
|
|
50
|
+
if (this.dtPicker && !this.disabled) {
|
|
50
51
|
this.dtPicker.open();
|
|
51
52
|
event.stopPropagation();
|
|
52
53
|
}
|
|
@@ -54,10 +55,10 @@ class OwlDateTimeTriggerDirective {
|
|
|
54
55
|
watchStateChanges() {
|
|
55
56
|
this.stateChanges.unsubscribe();
|
|
56
57
|
const inputDisabled = this.dtPicker && this.dtPicker.dtInput ?
|
|
57
|
-
this.dtPicker.dtInput.disabledChange :
|
|
58
|
+
this.dtPicker.dtInput.disabledChange.asObservable() : EMPTY;
|
|
58
59
|
const pickerDisabled = this.dtPicker ?
|
|
59
|
-
this.dtPicker.disabledChange :
|
|
60
|
-
this.stateChanges = merge(
|
|
60
|
+
this.dtPicker.disabledChange.asObservable() : EMPTY;
|
|
61
|
+
this.stateChanges = merge(pickerDisabled, inputDisabled)
|
|
61
62
|
.subscribe(() => {
|
|
62
63
|
this.changeDetector.markForCheck();
|
|
63
64
|
});
|
|
@@ -85,13 +86,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
85
86
|
/**
|
|
86
87
|
* date-time-format.class
|
|
87
88
|
*/
|
|
88
|
-
/** InjectionToken
|
|
89
|
+
/** InjectionToken для переопределения формата даты и времени */
|
|
89
90
|
const OWL_DATE_TIME_FORMATS = new InjectionToken('OWL_DATE_TIME_FORMATS');
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
93
|
* date-time-adapter.class
|
|
93
94
|
*/
|
|
94
|
-
/** InjectionToken
|
|
95
|
+
/** InjectionToken для переопределения локали компонента выбора даты и времени */
|
|
95
96
|
const OWL_DATE_TIME_LOCALE = new InjectionToken('OWL_DATE_TIME_LOCALE', {
|
|
96
97
|
providedIn: 'root',
|
|
97
98
|
factory: OWL_DATE_TIME_LOCALE_FACTORY
|
|
@@ -100,30 +101,30 @@ const OWL_DATE_TIME_LOCALE = new InjectionToken('OWL_DATE_TIME_LOCALE', {
|
|
|
100
101
|
function OWL_DATE_TIME_LOCALE_FACTORY() {
|
|
101
102
|
return inject(LOCALE_ID);
|
|
102
103
|
}
|
|
103
|
-
/**
|
|
104
|
+
/** Провайдер токена OWL_DATE_TIME_LOCALE */
|
|
104
105
|
const OWL_DATE_TIME_LOCALE_PROVIDER = {
|
|
105
106
|
provide: OWL_DATE_TIME_LOCALE,
|
|
106
107
|
useExisting: LOCALE_ID
|
|
107
108
|
};
|
|
108
109
|
class DateTimeAdapter {
|
|
109
110
|
constructor() {
|
|
110
|
-
/**
|
|
111
|
+
/** Поток уведомлений об изменении локали */
|
|
111
112
|
this._localeChanges = new Subject();
|
|
112
113
|
this.firstMonthOfTheYear = 0;
|
|
113
114
|
this.firstDayOfTheWeek = 0;
|
|
114
|
-
/**
|
|
115
|
+
/** Количество миллисекунд в сутках */
|
|
115
116
|
this.millisecondsInDay = 86400000;
|
|
116
|
-
/**
|
|
117
|
+
/** Количество миллисекунд в минуте */
|
|
117
118
|
this.millisecondsInMinute = 60000;
|
|
118
119
|
}
|
|
119
120
|
get localeChanges() {
|
|
120
121
|
return this._localeChanges;
|
|
121
122
|
}
|
|
122
123
|
/**
|
|
123
|
-
*
|
|
124
|
-
* 1
|
|
125
|
-
* -1
|
|
126
|
-
* 0
|
|
124
|
+
* Сравнивает две указанные даты
|
|
125
|
+
* 1, если первая дата позже второй;
|
|
126
|
+
* -1, если первая дата раньше второй;
|
|
127
|
+
* 0, если даты равны
|
|
127
128
|
* */
|
|
128
129
|
compare(first, second) {
|
|
129
130
|
if (!this.isValid(first) || !this.isValid(second)) {
|
|
@@ -139,15 +140,15 @@ class DateTimeAdapter {
|
|
|
139
140
|
return 1;
|
|
140
141
|
}
|
|
141
142
|
else {
|
|
142
|
-
//
|
|
143
|
+
// Возвращает 0 при diff === 0 и NaN при diff === NaN
|
|
143
144
|
return diff;
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
/**
|
|
147
|
-
*
|
|
148
|
-
* 1
|
|
149
|
-
* -1
|
|
150
|
-
* 0
|
|
148
|
+
* Сравнивает годы двух указанных дат
|
|
149
|
+
* 1, если год первой даты больше года второй;
|
|
150
|
+
* -1, если год первой даты меньше года второй;
|
|
151
|
+
* 0, если обе даты относятся к одному году
|
|
151
152
|
* */
|
|
152
153
|
compareYear(first, second) {
|
|
153
154
|
if (!this.isValid(first) || !this.isValid(second)) {
|
|
@@ -167,13 +168,17 @@ class DateTimeAdapter {
|
|
|
167
168
|
}
|
|
168
169
|
}
|
|
169
170
|
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
171
|
+
* Пытается десериализовать значение в корректный объект даты
|
|
172
|
+
* В отличие от разбора
|
|
173
|
+
* пользовательского ввода, deserialize принимает только однозначные форматы, не зависящие
|
|
174
|
+
* от локали, например ISO 8601
|
|
175
|
+
* По умолчанию метод ничего не преобразует, а проверяет,
|
|
176
|
+
* что значение уже является корректным объектом даты или null
|
|
177
|
+
* Компонент выбора даты
|
|
178
|
+
* использует этот метод для входных значений, представляющих даты
|
|
179
|
+
* Переопределение
|
|
180
|
+
* метода позволяет передавать в такие свойства значения прямо с сервера,
|
|
181
|
+
* если реализовать десериализацию формата, используемого сервером
|
|
177
182
|
*/
|
|
178
183
|
deserialize(value) {
|
|
179
184
|
if (value == null ||
|
|
@@ -183,26 +188,26 @@ class DateTimeAdapter {
|
|
|
183
188
|
return this.invalid();
|
|
184
189
|
}
|
|
185
190
|
/**
|
|
186
|
-
*
|
|
191
|
+
* Устанавливает локаль для всех дат
|
|
187
192
|
*/
|
|
188
193
|
setLocale(locale) {
|
|
189
194
|
this.locale = locale;
|
|
190
195
|
this._localeChanges.next(locale);
|
|
191
196
|
}
|
|
192
197
|
/**
|
|
193
|
-
*
|
|
198
|
+
* Возвращает локаль для всех дат
|
|
194
199
|
* */
|
|
195
200
|
getLocale() {
|
|
196
201
|
return this.locale;
|
|
197
202
|
}
|
|
198
203
|
/**
|
|
199
|
-
*
|
|
204
|
+
* Ограничивает дату минимальным и максимальным значениями
|
|
200
205
|
*/
|
|
201
206
|
clampDate(date, min, max) {
|
|
202
|
-
if (min && this.compare(date, min) < 0) {
|
|
207
|
+
if (min != null && this.compare(date, min) < 0) {
|
|
203
208
|
return min;
|
|
204
209
|
}
|
|
205
|
-
if (max && this.compare(date, max) > 0) {
|
|
210
|
+
if (max != null && this.compare(date, max) > 0) {
|
|
206
211
|
return max;
|
|
207
212
|
}
|
|
208
213
|
return date;
|
|
@@ -285,55 +290,56 @@ class OwlDateTime {
|
|
|
285
290
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
286
291
|
this.dateTimeFormats = dateTimeFormats;
|
|
287
292
|
/**
|
|
288
|
-
*
|
|
293
|
+
* Нужно ли показывать поле секунд
|
|
289
294
|
*/
|
|
290
295
|
this._showSecondsTimer = false;
|
|
291
296
|
/**
|
|
292
|
-
*
|
|
297
|
+
* Используется ли 12-часовой формат времени
|
|
293
298
|
*/
|
|
294
299
|
this._hour12Timer = false;
|
|
295
300
|
/**
|
|
296
|
-
*
|
|
301
|
+
* Начальное представление календаря
|
|
297
302
|
*/
|
|
298
303
|
this.startView = DateView.MONTH;
|
|
299
304
|
/**
|
|
300
|
-
*
|
|
305
|
+
* Нужно ли показывать номера недель в календаре
|
|
301
306
|
* */
|
|
302
307
|
this.showCalendarWeeks = false;
|
|
303
308
|
/**
|
|
304
|
-
*
|
|
309
|
+
* Нужно ли показывать только представления года и нескольких лет
|
|
305
310
|
*/
|
|
306
311
|
this.yearOnly = false;
|
|
307
312
|
/**
|
|
308
|
-
*
|
|
313
|
+
* Нужно ли показывать только представление нескольких лет
|
|
309
314
|
*/
|
|
310
315
|
this.multiyearOnly = false;
|
|
311
316
|
/**
|
|
312
|
-
*
|
|
317
|
+
* Количество часов за один шаг
|
|
313
318
|
*/
|
|
314
319
|
this._stepHour = 1;
|
|
315
320
|
/**
|
|
316
|
-
*
|
|
321
|
+
* Количество минут за один шаг
|
|
317
322
|
*/
|
|
318
323
|
this._stepMinute = 1;
|
|
319
324
|
/**
|
|
320
|
-
*
|
|
325
|
+
* Количество секунд за один шаг
|
|
321
326
|
*/
|
|
322
327
|
this._stepSecond = 1;
|
|
323
328
|
/**
|
|
324
|
-
*
|
|
329
|
+
* Нужно ли скрывать даты соседних месяцев в начале или конце текущего месяца
|
|
325
330
|
*/
|
|
326
331
|
this._hideOtherMonths = false;
|
|
327
332
|
/**
|
|
328
|
-
*
|
|
333
|
+
* Проверка доступности указанных даты и времени для выбора
|
|
329
334
|
*/
|
|
330
335
|
this.dateTimeChecker = (dateTime) => {
|
|
331
|
-
return (
|
|
336
|
+
return (dateTime != null &&
|
|
337
|
+
this.dateTimeAdapter.isValid(dateTime) &&
|
|
332
338
|
(!this.dateTimeFilter || this.dateTimeFilter(dateTime)) &&
|
|
333
|
-
(
|
|
339
|
+
(this.minDateTime == null ||
|
|
334
340
|
this.dateTimeAdapter.compare(dateTime, this.minDateTime) >=
|
|
335
341
|
0) &&
|
|
336
|
-
(
|
|
342
|
+
(this.maxDateTime == null ||
|
|
337
343
|
this.dateTimeAdapter.compare(dateTime, this.maxDateTime) <= 0));
|
|
338
344
|
};
|
|
339
345
|
if (!this.dateTimeAdapter) {
|
|
@@ -394,49 +400,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
394
400
|
class OwlDateTimeIntl {
|
|
395
401
|
constructor() {
|
|
396
402
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
403
|
+
* Поток событий изменения подписей для уведомления
|
|
404
|
+
* компонентов об изменении подписей после инициализации
|
|
399
405
|
*/
|
|
400
406
|
this.changes = new Subject();
|
|
401
|
-
/**
|
|
407
|
+
/** Подпись кнопки увеличения секунд для программ чтения с экрана */
|
|
402
408
|
this.upSecondLabel = 'Add a second';
|
|
403
|
-
/**
|
|
409
|
+
/** Подпись кнопки уменьшения секунд для программ чтения с экрана */
|
|
404
410
|
this.downSecondLabel = 'Minus a second';
|
|
405
|
-
/**
|
|
411
|
+
/** Подпись кнопки увеличения минут для программ чтения с экрана */
|
|
406
412
|
this.upMinuteLabel = 'Add a minute';
|
|
407
|
-
/**
|
|
413
|
+
/** Подпись кнопки уменьшения минут для программ чтения с экрана */
|
|
408
414
|
this.downMinuteLabel = 'Minus a minute';
|
|
409
|
-
/**
|
|
415
|
+
/** Подпись кнопки увеличения часов для программ чтения с экрана */
|
|
410
416
|
this.upHourLabel = 'Add a hour';
|
|
411
|
-
/**
|
|
417
|
+
/** Подпись кнопки уменьшения часов для программ чтения с экрана */
|
|
412
418
|
this.downHourLabel = 'Minus a hour';
|
|
413
|
-
/**
|
|
419
|
+
/** Подпись кнопки предыдущего месяца для программ чтения с экрана */
|
|
414
420
|
this.prevMonthLabel = 'Previous month';
|
|
415
|
-
/**
|
|
421
|
+
/** Подпись кнопки следующего месяца для программ чтения с экрана */
|
|
416
422
|
this.nextMonthLabel = 'Next month';
|
|
417
|
-
/**
|
|
423
|
+
/** Подпись кнопки предыдущего года для программ чтения с экрана */
|
|
418
424
|
this.prevYearLabel = 'Previous year';
|
|
419
|
-
/**
|
|
425
|
+
/** Подпись кнопки следующего года для программ чтения с экрана */
|
|
420
426
|
this.nextYearLabel = 'Next year';
|
|
421
|
-
/**
|
|
427
|
+
/** Подпись кнопки предыдущей группы лет для программ чтения с экрана */
|
|
422
428
|
this.prevMultiYearLabel = 'Previous 21 years';
|
|
423
|
-
/**
|
|
429
|
+
/** Подпись кнопки следующей группы лет для программ чтения с экрана */
|
|
424
430
|
this.nextMultiYearLabel = 'Next 21 years';
|
|
425
|
-
/**
|
|
431
|
+
/** Подпись кнопки перехода к представлению месяца для программ чтения с экрана */
|
|
426
432
|
this.switchToMonthViewLabel = 'Change to month view';
|
|
427
|
-
/**
|
|
433
|
+
/** Подпись кнопки перехода к представлению года для программ чтения с экрана */
|
|
428
434
|
this.switchToMultiYearViewLabel = 'Choose month and year';
|
|
429
|
-
/**
|
|
435
|
+
/** Подпись кнопки отмены */
|
|
430
436
|
this.cancelBtnLabel = 'Cancel';
|
|
431
|
-
/**
|
|
437
|
+
/** Подпись кнопки подтверждения */
|
|
432
438
|
this.setBtnLabel = 'Set';
|
|
433
|
-
/**
|
|
439
|
+
/** Подпись начала диапазона ('from') в информации о выбранных датах */
|
|
434
440
|
this.rangeFromLabel = 'From';
|
|
435
|
-
/**
|
|
441
|
+
/** Подпись конца диапазона ('to') в информации о выбранных датах */
|
|
436
442
|
this.rangeToLabel = 'To';
|
|
437
|
-
/**
|
|
443
|
+
/** Подпись кнопки AM в 12-часовом формате */
|
|
438
444
|
this.hour12AMLabel = 'AM';
|
|
439
|
-
/**
|
|
445
|
+
/** Подпись кнопки PM в 12-часовом формате */
|
|
440
446
|
this.hour12PMLabel = 'PM';
|
|
441
447
|
}
|
|
442
448
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlDateTimeIntl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
@@ -475,33 +481,41 @@ class OwlCalendarBodyComponent {
|
|
|
475
481
|
constructor(elmRef, ngZone) {
|
|
476
482
|
this.elmRef = elmRef;
|
|
477
483
|
this.ngZone = ngZone;
|
|
484
|
+
this.injector = inject(Injector);
|
|
485
|
+
this.destroyRef = inject(DestroyRef);
|
|
478
486
|
/**
|
|
479
|
-
*
|
|
487
|
+
* Номер активной ячейки в таблице
|
|
480
488
|
*/
|
|
481
489
|
this.activeCell = 0;
|
|
482
490
|
/**
|
|
483
|
-
*
|
|
491
|
+
* Количество столбцов в таблице
|
|
484
492
|
* */
|
|
485
493
|
this.numCols = 7;
|
|
486
494
|
/**
|
|
487
|
-
*
|
|
495
|
+
* Соотношение ширины и высоты ячеек таблицы
|
|
488
496
|
*/
|
|
489
497
|
this.cellRatio = 1;
|
|
490
498
|
/**
|
|
491
|
-
*
|
|
499
|
+
* Выбранное значение в таблице
|
|
500
|
+
* */
|
|
501
|
+
this.selectedValues = [];
|
|
502
|
+
/**
|
|
503
|
+
* Событие выбора ячейки календаря
|
|
492
504
|
* */
|
|
493
505
|
this.select = new EventEmitter();
|
|
494
506
|
}
|
|
495
507
|
ngOnInit() { }
|
|
496
508
|
selectCell(cell) {
|
|
497
|
-
|
|
509
|
+
if (cell.enabled) {
|
|
510
|
+
this.select.emit(cell);
|
|
511
|
+
}
|
|
498
512
|
}
|
|
499
513
|
isActiveCell(rowIndex, colIndex) {
|
|
500
514
|
const cellNumber = rowIndex * this.numCols + colIndex;
|
|
501
515
|
return cellNumber === this.activeCell;
|
|
502
516
|
}
|
|
503
517
|
/**
|
|
504
|
-
*
|
|
518
|
+
* Проверяет, выбрана ли ячейка
|
|
505
519
|
*/
|
|
506
520
|
isSelected(value) {
|
|
507
521
|
if (!this.selectedValues || this.selectedValues.length === 0) {
|
|
@@ -511,19 +525,19 @@ class OwlCalendarBodyComponent {
|
|
|
511
525
|
return value === this.selectedValues[0];
|
|
512
526
|
}
|
|
513
527
|
if (this.isInRangeMode) {
|
|
514
|
-
const fromValue = this.selectedValues[0];
|
|
515
|
-
const toValue = this.selectedValues[1];
|
|
528
|
+
const fromValue = this.selectedValues?.[0];
|
|
529
|
+
const toValue = this.selectedValues?.[1];
|
|
516
530
|
return value === fromValue || value === toValue;
|
|
517
531
|
}
|
|
518
532
|
}
|
|
519
533
|
/**
|
|
520
|
-
*
|
|
534
|
+
* Проверяет, входит ли ячейка в диапазон
|
|
521
535
|
* */
|
|
522
536
|
isInRange(value) {
|
|
523
537
|
if (this.isInRangeMode) {
|
|
524
|
-
const fromValue = this.selectedValues[0];
|
|
525
|
-
const toValue = this.selectedValues[1];
|
|
526
|
-
if (fromValue
|
|
538
|
+
const fromValue = this.selectedValues?.[0];
|
|
539
|
+
const toValue = this.selectedValues?.[1];
|
|
540
|
+
if (fromValue != null && toValue != null) {
|
|
527
541
|
return value >= fromValue && value <= toValue;
|
|
528
542
|
}
|
|
529
543
|
else {
|
|
@@ -532,37 +546,37 @@ class OwlCalendarBodyComponent {
|
|
|
532
546
|
}
|
|
533
547
|
}
|
|
534
548
|
/**
|
|
535
|
-
*
|
|
549
|
+
* Проверяет, соответствует ли ячейка началу диапазона
|
|
536
550
|
* */
|
|
537
551
|
isRangeFrom(value) {
|
|
538
552
|
if (this.isInRangeMode) {
|
|
539
|
-
const fromValue = this.selectedValues[0];
|
|
540
|
-
return fromValue
|
|
553
|
+
const fromValue = this.selectedValues?.[0];
|
|
554
|
+
return fromValue != null && value === fromValue;
|
|
541
555
|
}
|
|
542
556
|
}
|
|
543
557
|
/**
|
|
544
|
-
*
|
|
558
|
+
* Проверяет, соответствует ли ячейка концу диапазона
|
|
545
559
|
* */
|
|
546
560
|
isRangeTo(value) {
|
|
547
561
|
if (this.isInRangeMode) {
|
|
548
|
-
const toValue = this.selectedValues[1];
|
|
549
|
-
return toValue
|
|
562
|
+
const toValue = this.selectedValues?.[1];
|
|
563
|
+
return toValue != null && value === toValue;
|
|
550
564
|
}
|
|
551
565
|
}
|
|
552
566
|
/**
|
|
553
|
-
*
|
|
567
|
+
* Переводит фокус на активную ячейку
|
|
554
568
|
* */
|
|
555
569
|
focusActiveCell() {
|
|
556
|
-
this.
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
}
|
|
565
|
-
});
|
|
570
|
+
if (this.destroyRef.destroyed) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
this.focusRef?.destroy();
|
|
574
|
+
this.focusRef = afterNextRender({
|
|
575
|
+
write: () => {
|
|
576
|
+
this.focusRef = undefined;
|
|
577
|
+
this.elmRef.nativeElement.querySelector('.owl-dt-calendar-cell-active')?.focus();
|
|
578
|
+
}
|
|
579
|
+
}, { injector: this.injector });
|
|
566
580
|
}
|
|
567
581
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlCalendarBodyComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
568
582
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: OwlCalendarBodyComponent, isStandalone: false, selector: "[owl-date-time-calendar-body]", inputs: { activeCell: "activeCell", rows: "rows", numCols: "numCols", cellRatio: "cellRatio", todayValue: "todayValue", selectedValues: "selectedValues", selectMode: "selectMode" }, outputs: { select: "select" }, host: { properties: { "class.owl-dt-calendar-body": "owlDTCalendarBodyClass" } }, exportAs: ["owlDateTimeCalendarBody"], ngImport: i0, template: "@for (row of rows; track $index; let rowIndex = $index) {\r\n <tr role=\"row\">\r\n @for (item of row; track $index; let colIndex = $index) {\r\n <td\r\n class=\"owl-dt-calendar-cell {{ item.cellClass }}\"\r\n [tabindex]=\"isActiveCell(rowIndex, colIndex) ? 0 : -1\"\r\n [class.owl-dt-calendar-cell-active]=\"\r\n isActiveCell(rowIndex, colIndex)\r\n \"\r\n [class.owl-dt-calendar-cell-disabled]=\"!item.enabled\"\r\n [class.owl-dt-calendar-cell-in-range]=\"isInRange(item.value)\"\r\n [class.owl-dt-calendar-cell-range-from]=\"\r\n isRangeFrom(item.value)\r\n \"\r\n [class.owl-dt-calendar-cell-range-to]=\"isRangeTo(item.value)\"\r\n [attr.aria-label]=\"item.ariaLabel\"\r\n [attr.aria-disabled]=\"!item.enabled || null\"\r\n [attr.aria-current]=\"item.value === todayValue ? 'date' : null\"\r\n [attr.aria-selected]=\"isSelected(item.value)\"\r\n [style.width.%]=\"100 / numCols\"\r\n [style.paddingTop.%]=\"(50 * cellRatio) / numCols\"\r\n [style.paddingBottom.%]=\"(50 * cellRatio) / numCols\"\r\n (click)=\"selectCell(item)\"\r\n >\r\n <span\r\n class=\"owl-dt-calendar-cell-content\"\r\n [ngClass]=\"{\r\n 'owl-dt-calendar-cell-out': item.out,\r\n 'owl-dt-calendar-cell-today': item.value === todayValue,\r\n 'owl-dt-calendar-cell-selected': isSelected(item.value),\r\n }\"\r\n >\r\n {{ item.displayValue }}\r\n </span>\r\n </td>\r\n }\r\n </tr>\r\n}\r\n", styles: [""], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
@@ -598,7 +612,7 @@ function multiYearOptionsFactory(options) {
|
|
|
598
612
|
}
|
|
599
613
|
class DefaultOptions {
|
|
600
614
|
static create() {
|
|
601
|
-
//
|
|
615
|
+
// Всегда возвращаем новый экземпляр
|
|
602
616
|
return {
|
|
603
617
|
multiYear: {
|
|
604
618
|
yearRows: 7,
|
|
@@ -652,7 +666,7 @@ class OwlMultiYearViewComponent {
|
|
|
652
666
|
return this._selecteds;
|
|
653
667
|
}
|
|
654
668
|
set selecteds(values) {
|
|
655
|
-
this._selecteds = values.map((v) => {
|
|
669
|
+
this._selecteds = (values ?? []).map((v) => {
|
|
656
670
|
v = this.dateTimeAdapter.deserialize(v);
|
|
657
671
|
return this.getValidDate(v);
|
|
658
672
|
});
|
|
@@ -664,8 +678,8 @@ class OwlMultiYearViewComponent {
|
|
|
664
678
|
set pickerDateTime(value) {
|
|
665
679
|
const oldDateTime = this._pickerDateTime;
|
|
666
680
|
value = this.dateTimeAdapter.deserialize(value);
|
|
667
|
-
this._pickerDateTime = this.getValidDate(value)
|
|
668
|
-
if (oldDateTime && this._pickerDateTime &&
|
|
681
|
+
this._pickerDateTime = this.getValidDate(value) ?? this.dateTimeAdapter.now();
|
|
682
|
+
if (oldDateTime != null && this._pickerDateTime != null &&
|
|
669
683
|
!this.isSameYearList(oldDateTime, this._pickerDateTime)) {
|
|
670
684
|
this.generateYearList();
|
|
671
685
|
}
|
|
@@ -716,8 +730,8 @@ class OwlMultiYearViewComponent {
|
|
|
716
730
|
|| this.selectMode === 'rangeTo';
|
|
717
731
|
}
|
|
718
732
|
get activeCell() {
|
|
719
|
-
if (this._pickerDateTime) {
|
|
720
|
-
return this.dateTimeAdapter.getYear(this._pickerDateTime)
|
|
733
|
+
if (this._pickerDateTime != null) {
|
|
734
|
+
return this.dateTimeAdapter.getYear(this._pickerDateTime) - this.getYearListStart(this._pickerDateTime);
|
|
721
735
|
}
|
|
722
736
|
}
|
|
723
737
|
get tableHeader() {
|
|
@@ -743,23 +757,28 @@ class OwlMultiYearViewComponent {
|
|
|
743
757
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
744
758
|
this.options = options;
|
|
745
759
|
/**
|
|
746
|
-
*
|
|
760
|
+
* Режим выбора даты
|
|
747
761
|
* */
|
|
748
762
|
this._selectMode = 'single';
|
|
749
763
|
this._selecteds = [];
|
|
750
764
|
this.initiated = false;
|
|
751
765
|
/**
|
|
752
|
-
*
|
|
766
|
+
* Обработчик выбора нового месяца
|
|
753
767
|
* */
|
|
754
768
|
this.change = new EventEmitter();
|
|
755
769
|
/**
|
|
756
|
-
*
|
|
770
|
+
* Передаёт выбранный год, не изменяя выбранную дату
|
|
757
771
|
* */
|
|
758
772
|
this.yearSelected = new EventEmitter();
|
|
759
|
-
/**
|
|
773
|
+
/** Событие активации любой даты */
|
|
760
774
|
this.pickerDateTimeChange = new EventEmitter();
|
|
761
|
-
/**
|
|
775
|
+
/** Событие выбора ячейки календаря клавишей Enter */
|
|
762
776
|
this.keyboardEnter = new EventEmitter();
|
|
777
|
+
this.pickerIntl.changes.pipe(takeUntilDestroyed()).subscribe(() => this.cdRef.markForCheck());
|
|
778
|
+
this.dateTimeAdapter.localeChanges.pipe(takeUntilDestroyed()).subscribe(() => {
|
|
779
|
+
this.generateYearList();
|
|
780
|
+
this.cdRef.markForCheck();
|
|
781
|
+
});
|
|
763
782
|
}
|
|
764
783
|
ngOnInit() {
|
|
765
784
|
}
|
|
@@ -769,10 +788,12 @@ class OwlMultiYearViewComponent {
|
|
|
769
788
|
this.initiated = true;
|
|
770
789
|
}
|
|
771
790
|
/**
|
|
772
|
-
*
|
|
791
|
+
* Обрабатывает выбор ячейки календаря
|
|
773
792
|
*/
|
|
774
793
|
selectCalendarCell(cell) {
|
|
775
|
-
|
|
794
|
+
if (cell.enabled) {
|
|
795
|
+
this.selectYear(cell.value);
|
|
796
|
+
}
|
|
776
797
|
}
|
|
777
798
|
selectYear(year) {
|
|
778
799
|
this.yearSelected.emit(this.dateTimeAdapter.createDate(year, this.dateTimeAdapter.firstMonthOfTheYear, 1));
|
|
@@ -782,7 +803,7 @@ class OwlMultiYearViewComponent {
|
|
|
782
803
|
this.change.emit(selected);
|
|
783
804
|
}
|
|
784
805
|
/**
|
|
785
|
-
*
|
|
806
|
+
* Создаёт список предыдущих лет
|
|
786
807
|
* */
|
|
787
808
|
prevYearList(event) {
|
|
788
809
|
this._pickerDateTime = this.dateTimeAdapter.addCalendarYears(this.pickerDateTime, -1 * this.options.yearsPerRow * this.options.yearRows);
|
|
@@ -790,7 +811,7 @@ class OwlMultiYearViewComponent {
|
|
|
790
811
|
event.preventDefault();
|
|
791
812
|
}
|
|
792
813
|
/**
|
|
793
|
-
*
|
|
814
|
+
* Создаёт список следующих лет
|
|
794
815
|
* */
|
|
795
816
|
nextYearList(event) {
|
|
796
817
|
this._pickerDateTime = this.dateTimeAdapter.addCalendarYears(this.pickerDateTime, this.options.yearsPerRow * this.options.yearRows);
|
|
@@ -798,9 +819,12 @@ class OwlMultiYearViewComponent {
|
|
|
798
819
|
event.preventDefault();
|
|
799
820
|
}
|
|
800
821
|
generateYearList() {
|
|
822
|
+
if (this._pickerDateTime == null) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
801
825
|
this._years = [];
|
|
802
826
|
const pickerDateTimeYear = this.dateTimeAdapter.getYear(this._pickerDateTime);
|
|
803
|
-
const offset = pickerDateTimeYear
|
|
827
|
+
const offset = pickerDateTimeYear - this.getYearListStart(this._pickerDateTime);
|
|
804
828
|
for (let i = 0; i < this.options.yearRows; i++) {
|
|
805
829
|
const row = [];
|
|
806
830
|
for (let j = 0; j < this.options.yearsPerRow; j++) {
|
|
@@ -812,63 +836,62 @@ class OwlMultiYearViewComponent {
|
|
|
812
836
|
}
|
|
813
837
|
return;
|
|
814
838
|
}
|
|
815
|
-
/**
|
|
839
|
+
/** Доступна ли кнопка перехода к предыдущему периоду */
|
|
816
840
|
previousEnabled() {
|
|
817
|
-
|
|
818
|
-
return true;
|
|
819
|
-
}
|
|
820
|
-
return !this.minDate || !this.isSameYearList(this._pickerDateTime, this.minDate);
|
|
841
|
+
return this.minDate == null || this.getYearListStart(this._pickerDateTime) > this.getYearListStart(this.minDate);
|
|
821
842
|
}
|
|
822
|
-
/**
|
|
843
|
+
/** Доступна ли кнопка перехода к следующему периоду */
|
|
823
844
|
nextEnabled() {
|
|
824
|
-
return
|
|
845
|
+
return this.maxDate == null || this.getYearListStart(this._pickerDateTime) < this.getYearListStart(this.maxDate);
|
|
825
846
|
}
|
|
826
847
|
handleCalendarKeydown(event) {
|
|
827
848
|
let dateTime;
|
|
828
849
|
switch (event.keyCode) {
|
|
829
|
-
//
|
|
850
|
+
// На один год назад
|
|
830
851
|
case LEFT_ARROW:
|
|
831
852
|
dateTime = this.dateTimeAdapter.addCalendarYears(this._pickerDateTime, -1);
|
|
832
853
|
this.pickerDateTimeChange.emit(dateTime);
|
|
833
854
|
break;
|
|
834
|
-
//
|
|
855
|
+
// На один год вперёд
|
|
835
856
|
case RIGHT_ARROW:
|
|
836
857
|
dateTime = this.dateTimeAdapter.addCalendarYears(this._pickerDateTime, 1);
|
|
837
858
|
this.pickerDateTimeChange.emit(dateTime);
|
|
838
859
|
break;
|
|
839
|
-
//
|
|
860
|
+
// На три года назад
|
|
840
861
|
case UP_ARROW:
|
|
841
862
|
dateTime = this.dateTimeAdapter.addCalendarYears(this._pickerDateTime, -1 * this.options.yearsPerRow);
|
|
842
863
|
this.pickerDateTimeChange.emit(dateTime);
|
|
843
864
|
break;
|
|
844
|
-
//
|
|
865
|
+
// На три года вперёд
|
|
845
866
|
case DOWN_ARROW:
|
|
846
867
|
dateTime = this.dateTimeAdapter.addCalendarYears(this._pickerDateTime, this.options.yearsPerRow);
|
|
847
868
|
this.pickerDateTimeChange.emit(dateTime);
|
|
848
869
|
break;
|
|
849
|
-
//
|
|
870
|
+
// К первому году на текущей странице
|
|
850
871
|
case HOME:
|
|
851
|
-
dateTime = this.dateTimeAdapter.addCalendarYears(this._pickerDateTime, -this.
|
|
872
|
+
dateTime = this.dateTimeAdapter.addCalendarYears(this._pickerDateTime, -this.activeCell);
|
|
852
873
|
this.pickerDateTimeChange.emit(dateTime);
|
|
853
874
|
break;
|
|
854
|
-
//
|
|
875
|
+
// К последнему году на текущей странице
|
|
855
876
|
case END:
|
|
856
|
-
dateTime = this.dateTimeAdapter.addCalendarYears(this._pickerDateTime, (this.options.yearsPerRow * this.options.yearRows) - this.
|
|
877
|
+
dateTime = this.dateTimeAdapter.addCalendarYears(this._pickerDateTime, (this.options.yearsPerRow * this.options.yearRows) - this.activeCell - 1);
|
|
857
878
|
this.pickerDateTimeChange.emit(dateTime);
|
|
858
879
|
break;
|
|
859
|
-
//
|
|
880
|
+
// На одну страницу лет (или десять страниц) назад
|
|
860
881
|
case PAGE_UP:
|
|
861
882
|
dateTime = this.dateTimeAdapter.addCalendarYears(this.pickerDateTime, event.altKey ? -10 * (this.options.yearsPerRow * this.options.yearRows) : -1 * (this.options.yearsPerRow * this.options.yearRows));
|
|
862
883
|
this.pickerDateTimeChange.emit(dateTime);
|
|
863
884
|
break;
|
|
864
|
-
//
|
|
885
|
+
// На одну страницу лет (или десять страниц) вперёд
|
|
865
886
|
case PAGE_DOWN:
|
|
866
887
|
dateTime = this.dateTimeAdapter.addCalendarYears(this.pickerDateTime, event.altKey ? 10 * (this.options.yearsPerRow * this.options.yearRows) : (this.options.yearsPerRow * this.options.yearRows));
|
|
867
888
|
this.pickerDateTimeChange.emit(dateTime);
|
|
868
889
|
break;
|
|
869
890
|
case ENTER:
|
|
870
|
-
this.
|
|
871
|
-
|
|
891
|
+
if (this.isYearEnabled(this.dateTimeAdapter.getYear(this._pickerDateTime))) {
|
|
892
|
+
this.selectYear(this.dateTimeAdapter.getYear(this._pickerDateTime));
|
|
893
|
+
this.keyboardEnter.emit();
|
|
894
|
+
}
|
|
872
895
|
break;
|
|
873
896
|
default:
|
|
874
897
|
return;
|
|
@@ -877,7 +900,7 @@ class OwlMultiYearViewComponent {
|
|
|
877
900
|
event.preventDefault();
|
|
878
901
|
}
|
|
879
902
|
/**
|
|
880
|
-
*
|
|
903
|
+
* Создаёт CalendarCell для указанного года
|
|
881
904
|
*/
|
|
882
905
|
createYearCell(year) {
|
|
883
906
|
const startDateOfYear = this.dateTimeAdapter.createDate(year, this.dateTimeAdapter.firstMonthOfTheYear, 1);
|
|
@@ -887,7 +910,7 @@ class OwlMultiYearViewComponent {
|
|
|
887
910
|
}
|
|
888
911
|
setSelectedYears() {
|
|
889
912
|
this._selectedYears = [];
|
|
890
|
-
if (this.isInSingleMode && this.selected) {
|
|
913
|
+
if (this.isInSingleMode && this.selected != null) {
|
|
891
914
|
this._selectedYears[0] = this.dateTimeAdapter.getYear(this.selected);
|
|
892
915
|
}
|
|
893
916
|
if (this.isInRangeMode && this.selecteds) {
|
|
@@ -901,33 +924,38 @@ class OwlMultiYearViewComponent {
|
|
|
901
924
|
});
|
|
902
925
|
}
|
|
903
926
|
}
|
|
904
|
-
/**
|
|
927
|
+
/** Доступен ли указанный год для выбора */
|
|
905
928
|
isYearEnabled(year) {
|
|
906
|
-
//
|
|
929
|
+
// Отключаем выбор года, если он позже maxDate или раньше minDate
|
|
907
930
|
if (year === undefined || year === null ||
|
|
908
|
-
(this.maxDate && year > this.dateTimeAdapter.getYear(this.maxDate)) ||
|
|
909
|
-
(this.minDate && year < this.dateTimeAdapter.getYear(this.minDate))) {
|
|
931
|
+
(this.maxDate != null && year > this.dateTimeAdapter.getYear(this.maxDate)) ||
|
|
932
|
+
(this.minDate != null && year < this.dateTimeAdapter.getYear(this.minDate))) {
|
|
910
933
|
return false;
|
|
911
934
|
}
|
|
912
|
-
//
|
|
935
|
+
// Разрешаем выбор, если проверки пройдены и фильтр не задан
|
|
913
936
|
if (!this.dateFilter) {
|
|
914
937
|
return true;
|
|
915
938
|
}
|
|
916
939
|
const firstOfYear = this.dateTimeAdapter.createDate(year, this.dateTimeAdapter.firstMonthOfTheYear, 1);
|
|
917
|
-
//
|
|
940
|
+
// Считаем год доступным для выбора, если доступна хотя бы одна дата в нём
|
|
918
941
|
for (let date = firstOfYear; this.dateTimeAdapter.getYear(date) === year; date = this.dateTimeAdapter.addCalendarDays(date, 1)) {
|
|
919
|
-
if (this.dateFilter(date)
|
|
942
|
+
if (this.dateFilter(date) &&
|
|
943
|
+
(this.minDate == null || this.dateTimeAdapter.compare(date, this.minDate) >= 0) &&
|
|
944
|
+
(this.maxDate == null || this.dateTimeAdapter.compare(date, this.maxDate) <= 0)) {
|
|
920
945
|
return true;
|
|
921
946
|
}
|
|
922
947
|
}
|
|
923
948
|
return false;
|
|
924
949
|
}
|
|
925
950
|
isSameYearList(date1, date2) {
|
|
926
|
-
return
|
|
927
|
-
|
|
951
|
+
return this.getYearListStart(date1) === this.getYearListStart(date2);
|
|
952
|
+
}
|
|
953
|
+
getYearListStart(date) {
|
|
954
|
+
const yearsPerPage = this.options.yearsPerRow * this.options.yearRows;
|
|
955
|
+
return Math.floor(this.dateTimeAdapter.getYear(date) / yearsPerPage) * yearsPerPage;
|
|
928
956
|
}
|
|
929
957
|
/**
|
|
930
|
-
*
|
|
958
|
+
* Возвращает корректный объект даты
|
|
931
959
|
*/
|
|
932
960
|
getValidDate(obj) {
|
|
933
961
|
return (this.dateTimeAdapter.isDateInstance(obj) && this.dateTimeAdapter.isValid(obj)) ? obj : null;
|
|
@@ -936,14 +964,14 @@ class OwlMultiYearViewComponent {
|
|
|
936
964
|
this.calendarBodyElm.focusActiveCell();
|
|
937
965
|
}
|
|
938
966
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlMultiYearViewComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: OwlDateTimeIntl }, { token: DateTimeAdapter, optional: true }, { token: OptionsTokens.multiYear }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
939
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: OwlMultiYearViewComponent, isStandalone: false, selector: "owl-date-time-multi-year-view", inputs: { selectMode: "selectMode", selected: "selected", selecteds: "selecteds", pickerDateTime: "pickerDateTime", dateFilter: "dateFilter", minDate: "minDate", maxDate: "maxDate" }, outputs: { change: "change", yearSelected: "yearSelected", pickerDateTimeChange: "pickerDateTimeChange", keyboardEnter: "keyboardEnter" }, host: { properties: { "class.owl-dt-calendar-view": "owlDTCalendarView", "class.owl-dt-calendar-multi-year-view": "owlDTCalendarMultiYearView" } }, viewQueries: [{ propertyName: "calendarBodyElm", first: true, predicate: OwlCalendarBodyComponent, descendants: true, static: true }], ngImport: i0, template: "<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n [disabled]=\"!previousEnabled()\" [attr.aria-label]=\"prevButtonLabel\"\r\n type=\"button\" tabindex=\"0\" (click)=\"prevYearList($event)\">\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG
|
|
967
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: OwlMultiYearViewComponent, isStandalone: false, selector: "owl-date-time-multi-year-view", inputs: { selectMode: "selectMode", selected: "selected", selecteds: "selecteds", pickerDateTime: "pickerDateTime", dateFilter: "dateFilter", minDate: "minDate", maxDate: "maxDate" }, outputs: { change: "change", yearSelected: "yearSelected", pickerDateTimeChange: "pickerDateTimeChange", keyboardEnter: "keyboardEnter" }, host: { properties: { "class.owl-dt-calendar-view": "owlDTCalendarView", "class.owl-dt-calendar-multi-year-view": "owlDTCalendarMultiYearView" } }, viewQueries: [{ propertyName: "calendarBodyElm", first: true, predicate: OwlCalendarBodyComponent, descendants: true, static: true }], ngImport: i0, template: "<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n [disabled]=\"!previousEnabled()\" [attr.aria-label]=\"prevButtonLabel\"\r\n type=\"button\" tabindex=\"0\" (click)=\"prevYearList($event)\">\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043B\u0435\u0432\u043E\"> -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\" x=\"0px\" y=\"0px\" viewBox=\"0 0 250.738 250.738\"\r\n style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\"\r\n width=\"100%\" height=\"100%\">\r\n <path style=\"fill-rule: evenodd; clip-rule: evenodd;\" d=\"M96.633,125.369l95.053-94.533c7.101-7.055,7.101-18.492,0-25.546 c-7.1-7.054-18.613-7.054-25.714,0L58.989,111.689c-3.784,3.759-5.487,8.759-5.238,13.68c-0.249,4.922,1.454,9.921,5.238,13.681 l106.983,106.398c7.101,7.055,18.613,7.055,25.714,0c7.101-7.054,7.101-18.491,0-25.544L96.633,125.369z\"/>\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n</button>\r\n<table class=\"owl-dt-calendar-table owl-dt-calendar-multi-year-table\">\r\n <thead class=\"owl-dt-calendar-header\">\r\n <tr>\r\n <th [attr.colspan]=\"options.yearsPerRow\">{{tableHeader}}</th>\r\n </tr>\r\n </thead>\r\n <tbody owl-date-time-calendar-body role=\"grid\"\r\n [rows]=\"years\" [numCols]=\"options.yearsPerRow\" [cellRatio]=\"3 / 7\"\r\n [activeCell]=\"activeCell\"\r\n [todayValue]=\"todayYear\"\r\n [selectedValues]=\"selectedYears\"\r\n [selectMode]=\"selectMode\"\r\n (keydown)=\"handleCalendarKeydown($event)\"\r\n (select)=\"selectCalendarCell($event)\"></tbody>\r\n</table>\r\n<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n [disabled]=\"!nextEnabled()\" [attr.aria-label]=\"nextButtonLabel\"\r\n type=\"button\" tabindex=\"0\" (click)=\"nextYearList($event)\">\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043F\u0440\u0430\u0432\u043E\"> -->\r\n <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\r\n viewBox=\"0 0 250.738 250.738\" style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\">\r\n <path style=\"fill-rule:evenodd;clip-rule:evenodd;\" d=\"M191.75,111.689L84.766,5.291c-7.1-7.055-18.613-7.055-25.713,0\r\n c-7.101,7.054-7.101,18.49,0,25.544l95.053,94.534l-95.053,94.533c-7.101,7.054-7.101,18.491,0,25.545\r\n c7.1,7.054,18.613,7.054,25.713,0L191.75,139.05c3.784-3.759,5.487-8.759,5.238-13.681\r\n C197.237,120.447,195.534,115.448,191.75,111.689z\"/>\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n</button>\r\n", styles: [""], dependencies: [{ kind: "component", type: OwlCalendarBodyComponent, selector: "[owl-date-time-calendar-body]", inputs: ["activeCell", "rows", "numCols", "cellRatio", "todayValue", "selectedValues", "selectMode"], outputs: ["select"], exportAs: ["owlDateTimeCalendarBody"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
940
968
|
}
|
|
941
969
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlMultiYearViewComponent, decorators: [{
|
|
942
970
|
type: Component,
|
|
943
971
|
args: [{ selector: 'owl-date-time-multi-year-view', host: {
|
|
944
972
|
'[class.owl-dt-calendar-view]': 'owlDTCalendarView',
|
|
945
973
|
'[class.owl-dt-calendar-multi-year-view]': 'owlDTCalendarMultiYearView'
|
|
946
|
-
}, standalone: false, preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n [disabled]=\"!previousEnabled()\" [attr.aria-label]=\"prevButtonLabel\"\r\n type=\"button\" tabindex=\"0\" (click)=\"prevYearList($event)\">\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG
|
|
974
|
+
}, standalone: false, preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n [disabled]=\"!previousEnabled()\" [attr.aria-label]=\"prevButtonLabel\"\r\n type=\"button\" tabindex=\"0\" (click)=\"prevYearList($event)\">\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043B\u0435\u0432\u043E\"> -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\" x=\"0px\" y=\"0px\" viewBox=\"0 0 250.738 250.738\"\r\n style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\"\r\n width=\"100%\" height=\"100%\">\r\n <path style=\"fill-rule: evenodd; clip-rule: evenodd;\" d=\"M96.633,125.369l95.053-94.533c7.101-7.055,7.101-18.492,0-25.546 c-7.1-7.054-18.613-7.054-25.714,0L58.989,111.689c-3.784,3.759-5.487,8.759-5.238,13.68c-0.249,4.922,1.454,9.921,5.238,13.681 l106.983,106.398c7.101,7.055,18.613,7.055,25.714,0c7.101-7.054,7.101-18.491,0-25.544L96.633,125.369z\"/>\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n</button>\r\n<table class=\"owl-dt-calendar-table owl-dt-calendar-multi-year-table\">\r\n <thead class=\"owl-dt-calendar-header\">\r\n <tr>\r\n <th [attr.colspan]=\"options.yearsPerRow\">{{tableHeader}}</th>\r\n </tr>\r\n </thead>\r\n <tbody owl-date-time-calendar-body role=\"grid\"\r\n [rows]=\"years\" [numCols]=\"options.yearsPerRow\" [cellRatio]=\"3 / 7\"\r\n [activeCell]=\"activeCell\"\r\n [todayValue]=\"todayYear\"\r\n [selectedValues]=\"selectedYears\"\r\n [selectMode]=\"selectMode\"\r\n (keydown)=\"handleCalendarKeydown($event)\"\r\n (select)=\"selectCalendarCell($event)\"></tbody>\r\n</table>\r\n<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n [disabled]=\"!nextEnabled()\" [attr.aria-label]=\"nextButtonLabel\"\r\n type=\"button\" tabindex=\"0\" (click)=\"nextYearList($event)\">\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043F\u0440\u0430\u0432\u043E\"> -->\r\n <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\r\n viewBox=\"0 0 250.738 250.738\" style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\">\r\n <path style=\"fill-rule:evenodd;clip-rule:evenodd;\" d=\"M191.75,111.689L84.766,5.291c-7.1-7.055-18.613-7.055-25.713,0\r\n c-7.101,7.054-7.101,18.49,0,25.544l95.053,94.534l-95.053,94.533c-7.101,7.054-7.101,18.491,0,25.545\r\n c7.1,7.054,18.613,7.054,25.713,0L191.75,139.05c3.784-3.759,5.487-8.759,5.238-13.681\r\n C197.237,120.447,195.534,115.448,191.75,111.689z\"/>\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n</button>\r\n" }]
|
|
947
975
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: OwlDateTimeIntl }, { type: DateTimeAdapter, decorators: [{
|
|
948
976
|
type: Optional
|
|
949
977
|
}] }, { type: undefined, decorators: [{
|
|
@@ -1005,7 +1033,7 @@ class OwlYearViewComponent {
|
|
|
1005
1033
|
}
|
|
1006
1034
|
set selecteds(values) {
|
|
1007
1035
|
this._selecteds = [];
|
|
1008
|
-
for (let i = 0; i < values
|
|
1036
|
+
for (let i = 0; i < (values?.length ?? 0); i++) {
|
|
1009
1037
|
const value = this.dateTimeAdapter.deserialize(values[i]);
|
|
1010
1038
|
this._selecteds.push(this.getValidDate(value));
|
|
1011
1039
|
}
|
|
@@ -1018,7 +1046,7 @@ class OwlYearViewComponent {
|
|
|
1018
1046
|
const oldDateTime = this._pickerDateTime;
|
|
1019
1047
|
value = this.dateTimeAdapter.deserialize(value);
|
|
1020
1048
|
this._pickerDateTime =
|
|
1021
|
-
this.getValidDate(value)
|
|
1049
|
+
this.getValidDate(value) ?? this.dateTimeAdapter.now();
|
|
1022
1050
|
if (!this.hasSameYear(oldDateTime, this._pickerDateTime) &&
|
|
1023
1051
|
this.initiated) {
|
|
1024
1052
|
this.generateMonthList();
|
|
@@ -1057,7 +1085,7 @@ class OwlYearViewComponent {
|
|
|
1057
1085
|
return this._months;
|
|
1058
1086
|
}
|
|
1059
1087
|
get activeCell() {
|
|
1060
|
-
if (this._pickerDateTime) {
|
|
1088
|
+
if (this._pickerDateTime != null) {
|
|
1061
1089
|
return this.dateTimeAdapter.getMonth(this._pickerDateTime);
|
|
1062
1090
|
}
|
|
1063
1091
|
}
|
|
@@ -1077,33 +1105,34 @@ class OwlYearViewComponent {
|
|
|
1077
1105
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
1078
1106
|
this.dateTimeFormats = dateTimeFormats;
|
|
1079
1107
|
/**
|
|
1080
|
-
*
|
|
1108
|
+
* Режим выбора даты
|
|
1081
1109
|
* */
|
|
1082
1110
|
this._selectMode = 'single';
|
|
1083
1111
|
this._selecteds = [];
|
|
1084
1112
|
this.localeSub = Subscription.EMPTY;
|
|
1085
1113
|
this.initiated = false;
|
|
1086
1114
|
/**
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1115
|
+
* Массив номеров месяцев из selectedDates
|
|
1116
|
+
* Значение — номер месяца в текущем году
|
|
1089
1117
|
* */
|
|
1090
1118
|
this.selectedMonths = [];
|
|
1091
1119
|
/**
|
|
1092
|
-
*
|
|
1120
|
+
* Обработчик выбора нового месяца
|
|
1093
1121
|
* */
|
|
1094
1122
|
this.change = new EventEmitter();
|
|
1095
1123
|
/**
|
|
1096
|
-
*
|
|
1124
|
+
* Передаёт выбранный год, не изменяя выбранную дату
|
|
1097
1125
|
* */
|
|
1098
1126
|
this.monthSelected = new EventEmitter();
|
|
1099
|
-
/**
|
|
1127
|
+
/** Событие активации любой даты */
|
|
1100
1128
|
this.pickerDateTimeChange = new EventEmitter();
|
|
1101
|
-
/**
|
|
1129
|
+
/** Событие выбора ячейки календаря клавишей Enter */
|
|
1102
1130
|
this.keyboardEnter = new EventEmitter();
|
|
1103
1131
|
this.monthNames = this.dateTimeAdapter.getMonthNames('short');
|
|
1104
1132
|
}
|
|
1105
1133
|
ngOnInit() {
|
|
1106
1134
|
this.localeSub = this.dateTimeAdapter.localeChanges.subscribe(() => {
|
|
1135
|
+
this.monthNames = this.dateTimeAdapter.getMonthNames('short');
|
|
1107
1136
|
this.generateMonthList();
|
|
1108
1137
|
this.cdRef.markForCheck();
|
|
1109
1138
|
});
|
|
@@ -1116,13 +1145,15 @@ class OwlYearViewComponent {
|
|
|
1116
1145
|
this.localeSub.unsubscribe();
|
|
1117
1146
|
}
|
|
1118
1147
|
/**
|
|
1119
|
-
*
|
|
1148
|
+
* Обрабатывает выбор ячейки календаря
|
|
1120
1149
|
*/
|
|
1121
1150
|
selectCalendarCell(cell) {
|
|
1122
|
-
|
|
1151
|
+
if (cell.enabled) {
|
|
1152
|
+
this.selectMonth(cell.value);
|
|
1153
|
+
}
|
|
1123
1154
|
}
|
|
1124
1155
|
/**
|
|
1125
|
-
*
|
|
1156
|
+
* Обрабатывает выбор нового месяца
|
|
1126
1157
|
*/
|
|
1127
1158
|
selectMonth(month) {
|
|
1128
1159
|
const firstDateOfMonth = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(this.pickerDateTime), month, 1);
|
|
@@ -1132,55 +1163,57 @@ class OwlYearViewComponent {
|
|
|
1132
1163
|
this.change.emit(result);
|
|
1133
1164
|
}
|
|
1134
1165
|
/**
|
|
1135
|
-
*
|
|
1166
|
+
* Обрабатывает keydown в таблице календаря
|
|
1136
1167
|
*/
|
|
1137
1168
|
handleCalendarKeydown(event) {
|
|
1138
1169
|
let dateTime;
|
|
1139
1170
|
switch (event.keyCode) {
|
|
1140
|
-
//
|
|
1171
|
+
// На один месяц назад
|
|
1141
1172
|
case LEFT_ARROW:
|
|
1142
1173
|
dateTime = this.dateTimeAdapter.addCalendarMonths(this.pickerDateTime, -1);
|
|
1143
1174
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1144
1175
|
break;
|
|
1145
|
-
//
|
|
1176
|
+
// На один месяц вперёд
|
|
1146
1177
|
case RIGHT_ARROW:
|
|
1147
1178
|
dateTime = this.dateTimeAdapter.addCalendarMonths(this.pickerDateTime, 1);
|
|
1148
1179
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1149
1180
|
break;
|
|
1150
|
-
//
|
|
1181
|
+
// На три месяца назад
|
|
1151
1182
|
case UP_ARROW:
|
|
1152
1183
|
dateTime = this.dateTimeAdapter.addCalendarMonths(this.pickerDateTime, -3);
|
|
1153
1184
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1154
1185
|
break;
|
|
1155
|
-
//
|
|
1186
|
+
// На три месяца вперёд
|
|
1156
1187
|
case DOWN_ARROW:
|
|
1157
1188
|
dateTime = this.dateTimeAdapter.addCalendarMonths(this.pickerDateTime, 3);
|
|
1158
1189
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1159
1190
|
break;
|
|
1160
|
-
//
|
|
1191
|
+
// К первому месяцу текущего года
|
|
1161
1192
|
case HOME:
|
|
1162
1193
|
dateTime = this.dateTimeAdapter.addCalendarMonths(this.pickerDateTime, -this.dateTimeAdapter.getMonth(this.pickerDateTime));
|
|
1163
1194
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1164
1195
|
break;
|
|
1165
|
-
//
|
|
1196
|
+
// К последнему месяцу текущего года
|
|
1166
1197
|
case END:
|
|
1167
1198
|
dateTime = this.dateTimeAdapter.addCalendarMonths(this.pickerDateTime, 11 - this.dateTimeAdapter.getMonth(this.pickerDateTime));
|
|
1168
1199
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1169
1200
|
break;
|
|
1170
|
-
//
|
|
1201
|
+
// На один год (или десять лет) назад
|
|
1171
1202
|
case PAGE_UP:
|
|
1172
1203
|
dateTime = this.dateTimeAdapter.addCalendarYears(this.pickerDateTime, event.altKey ? -10 : -1);
|
|
1173
1204
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1174
1205
|
break;
|
|
1175
|
-
//
|
|
1206
|
+
// На один год (или десять лет) вперёд
|
|
1176
1207
|
case PAGE_DOWN:
|
|
1177
1208
|
dateTime = this.dateTimeAdapter.addCalendarYears(this.pickerDateTime, event.altKey ? 10 : 1);
|
|
1178
1209
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1179
1210
|
break;
|
|
1180
|
-
//
|
|
1211
|
+
// Выбирает текущий месяц
|
|
1181
1212
|
case ENTER:
|
|
1182
|
-
this.
|
|
1183
|
-
|
|
1213
|
+
if (this.isMonthEnabled(this.dateTimeAdapter.getMonth(this.pickerDateTime))) {
|
|
1214
|
+
this.selectMonth(this.dateTimeAdapter.getMonth(this.pickerDateTime));
|
|
1215
|
+
this.keyboardEnter.emit();
|
|
1216
|
+
}
|
|
1184
1217
|
break;
|
|
1185
1218
|
default:
|
|
1186
1219
|
return;
|
|
@@ -1189,10 +1222,10 @@ class OwlYearViewComponent {
|
|
|
1189
1222
|
event.preventDefault();
|
|
1190
1223
|
}
|
|
1191
1224
|
/**
|
|
1192
|
-
*
|
|
1225
|
+
* Создаёт список месяцев календаря
|
|
1193
1226
|
* */
|
|
1194
1227
|
generateMonthList() {
|
|
1195
|
-
if (
|
|
1228
|
+
if (this.pickerDateTime == null) {
|
|
1196
1229
|
return;
|
|
1197
1230
|
}
|
|
1198
1231
|
this.setSelectedMonths();
|
|
@@ -1210,7 +1243,7 @@ class OwlYearViewComponent {
|
|
|
1210
1243
|
return;
|
|
1211
1244
|
}
|
|
1212
1245
|
/**
|
|
1213
|
-
*
|
|
1246
|
+
* Создаёт CalendarCell для указанного месяца
|
|
1214
1247
|
*/
|
|
1215
1248
|
createMonthCell(month) {
|
|
1216
1249
|
const startDateOfMonth = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(this.pickerDateTime), month, 1);
|
|
@@ -1219,18 +1252,18 @@ class OwlYearViewComponent {
|
|
|
1219
1252
|
return new CalendarCell(month, this.monthNames[month - this.dateTimeAdapter.firstMonthOfTheYear], ariaLabel, this.isMonthEnabled(month), false, cellClass);
|
|
1220
1253
|
}
|
|
1221
1254
|
/**
|
|
1222
|
-
*
|
|
1255
|
+
* Проверяет доступность указанного месяца для выбора
|
|
1223
1256
|
*/
|
|
1224
1257
|
isMonthEnabled(month) {
|
|
1225
1258
|
const firstDateOfMonth = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(this.pickerDateTime), month, 1);
|
|
1226
|
-
//
|
|
1227
|
-
//
|
|
1259
|
+
// Если в месяце доступна для выбора хотя бы одна дата,
|
|
1260
|
+
// считаем месяц доступным для выбора
|
|
1228
1261
|
for (let date = firstDateOfMonth; this.dateTimeAdapter.getMonth(date) === month; date = this.dateTimeAdapter.addCalendarDays(date, 1)) {
|
|
1229
|
-
if (
|
|
1262
|
+
if (date != null &&
|
|
1230
1263
|
(!this.dateFilter || this.dateFilter(date)) &&
|
|
1231
|
-
(
|
|
1264
|
+
(this.minDate == null ||
|
|
1232
1265
|
this.dateTimeAdapter.compare(date, this.minDate) >= 0) &&
|
|
1233
|
-
(
|
|
1266
|
+
(this.maxDate == null ||
|
|
1234
1267
|
this.dateTimeAdapter.compare(date, this.maxDate) <= 0)) {
|
|
1235
1268
|
return true;
|
|
1236
1269
|
}
|
|
@@ -1238,15 +1271,15 @@ class OwlYearViewComponent {
|
|
|
1238
1271
|
return false;
|
|
1239
1272
|
}
|
|
1240
1273
|
/**
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1274
|
+
* Возвращает месяц указанной даты в текущем году
|
|
1275
|
+
* Возвращает null, если указанная дата находится в другом году
|
|
1243
1276
|
*/
|
|
1244
1277
|
getMonthInCurrentYear(date) {
|
|
1245
|
-
if (this.getValidDate(date) && this.getValidDate(this._pickerDateTime)) {
|
|
1278
|
+
if (this.getValidDate(date) != null && this.getValidDate(this._pickerDateTime) != null) {
|
|
1246
1279
|
const result = this.dateTimeAdapter.compareYear(date, this._pickerDateTime);
|
|
1247
|
-
// < 0:
|
|
1248
|
-
// > 0:
|
|
1249
|
-
// 0:
|
|
1280
|
+
// < 0: выбранная дата находится в предыдущем году, поэтому возвращаем -1
|
|
1281
|
+
// > 0: выбранная дата находится в следующем году, поэтому возвращаем 12
|
|
1282
|
+
// 0: оба значения находятся в одном году, поэтому возвращаем номер месяца
|
|
1250
1283
|
if (result < 0) {
|
|
1251
1284
|
return -1;
|
|
1252
1285
|
}
|
|
@@ -1262,13 +1295,13 @@ class OwlYearViewComponent {
|
|
|
1262
1295
|
}
|
|
1263
1296
|
}
|
|
1264
1297
|
/**
|
|
1265
|
-
*
|
|
1266
|
-
*
|
|
1267
|
-
*
|
|
1298
|
+
* Задаёт значение selectedMonths
|
|
1299
|
+
* В режиме single содержит одно значение — месяц выбранной даты
|
|
1300
|
+
* В режиме range содержит два значения: месяц fromValue и месяц toValue
|
|
1268
1301
|
* */
|
|
1269
1302
|
setSelectedMonths() {
|
|
1270
1303
|
this.selectedMonths = [];
|
|
1271
|
-
if (this.isInSingleMode && this.selected) {
|
|
1304
|
+
if (this.isInSingleMode && this.selected != null) {
|
|
1272
1305
|
this.selectedMonths[0] = this.getMonthInCurrentYear(this.selected);
|
|
1273
1306
|
}
|
|
1274
1307
|
if (this.isInRangeMode && this.selecteds) {
|
|
@@ -1277,16 +1310,16 @@ class OwlYearViewComponent {
|
|
|
1277
1310
|
}
|
|
1278
1311
|
}
|
|
1279
1312
|
/**
|
|
1280
|
-
*
|
|
1313
|
+
* Проверяет, находятся ли указанные даты в одном году
|
|
1281
1314
|
*/
|
|
1282
1315
|
hasSameYear(dateLeft, dateRight) {
|
|
1283
|
-
return !!(dateLeft &&
|
|
1284
|
-
dateRight &&
|
|
1316
|
+
return !!(dateLeft != null &&
|
|
1317
|
+
dateRight != null &&
|
|
1285
1318
|
this.dateTimeAdapter.getYear(dateLeft) ===
|
|
1286
1319
|
this.dateTimeAdapter.getYear(dateRight));
|
|
1287
1320
|
}
|
|
1288
1321
|
/**
|
|
1289
|
-
*
|
|
1322
|
+
* Возвращает корректный объект даты
|
|
1290
1323
|
*/
|
|
1291
1324
|
getValidDate(obj) {
|
|
1292
1325
|
return this.dateTimeAdapter.isDateInstance(obj) &&
|
|
@@ -1384,7 +1417,7 @@ class OwlMonthViewComponent {
|
|
|
1384
1417
|
return this._selecteds;
|
|
1385
1418
|
}
|
|
1386
1419
|
set selecteds(values) {
|
|
1387
|
-
this._selecteds = values.map(v => {
|
|
1420
|
+
this._selecteds = (values ?? []).map(v => {
|
|
1388
1421
|
v = this.dateTimeAdapter.deserialize(v);
|
|
1389
1422
|
return this.getValidDate(v);
|
|
1390
1423
|
});
|
|
@@ -1397,7 +1430,7 @@ class OwlMonthViewComponent {
|
|
|
1397
1430
|
const oldDateTime = this._pickerDateTime;
|
|
1398
1431
|
value = this.dateTimeAdapter.deserialize(value);
|
|
1399
1432
|
this._pickerDateTime =
|
|
1400
|
-
this.getValidDate(value)
|
|
1433
|
+
this.getValidDate(value) ?? this.dateTimeAdapter.now();
|
|
1401
1434
|
this.firstDateOfMonth = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(this._pickerDateTime), this.dateTimeAdapter.getMonth(this._pickerDateTime), 1);
|
|
1402
1435
|
if (!this.isSameMonth(oldDateTime, this._pickerDateTime) &&
|
|
1403
1436
|
this.initiated) {
|
|
@@ -1443,7 +1476,7 @@ class OwlMonthViewComponent {
|
|
|
1443
1476
|
return this._days;
|
|
1444
1477
|
}
|
|
1445
1478
|
get activeCell() {
|
|
1446
|
-
if (this.pickerDateTime) {
|
|
1479
|
+
if (this.pickerDateTime != null) {
|
|
1447
1480
|
return (this.dateTimeAdapter.getDate(this.pickerDateTime) +
|
|
1448
1481
|
this.firstRowOffset -
|
|
1449
1482
|
1);
|
|
@@ -1465,35 +1498,35 @@ class OwlMonthViewComponent {
|
|
|
1465
1498
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
1466
1499
|
this.dateTimeFormats = dateTimeFormats;
|
|
1467
1500
|
/**
|
|
1468
|
-
*
|
|
1501
|
+
* Нужно ли скрывать даты соседних месяцев в начале или конце текущего месяца
|
|
1469
1502
|
* */
|
|
1470
1503
|
this.hideOtherMonths = false;
|
|
1471
1504
|
/**
|
|
1472
|
-
*
|
|
1505
|
+
* Нужно ли показывать номера недель в календаре
|
|
1473
1506
|
* */
|
|
1474
1507
|
this.showCalendarWeeks = false;
|
|
1475
1508
|
this.isDefaultFirstDayOfWeek = true;
|
|
1476
1509
|
/**
|
|
1477
|
-
*
|
|
1510
|
+
* Режим выбора даты
|
|
1478
1511
|
* */
|
|
1479
1512
|
this._selectMode = 'single';
|
|
1480
1513
|
this._selecteds = [];
|
|
1481
1514
|
this.localeSub = Subscription.EMPTY;
|
|
1482
1515
|
this.initiated = false;
|
|
1483
1516
|
/**
|
|
1484
|
-
*
|
|
1485
|
-
*
|
|
1517
|
+
* Массив значений selectedDates
|
|
1518
|
+
* Значение — номер дня в текущем месяце
|
|
1486
1519
|
* */
|
|
1487
1520
|
this.selectedDates = [];
|
|
1488
1521
|
/**
|
|
1489
|
-
*
|
|
1522
|
+
* Обработчик выбора новой даты
|
|
1490
1523
|
* */
|
|
1491
1524
|
this.selectedChange = new EventEmitter();
|
|
1492
1525
|
/**
|
|
1493
|
-
*
|
|
1526
|
+
* Обработчик выбора любой даты
|
|
1494
1527
|
* */
|
|
1495
1528
|
this.userSelection = new EventEmitter();
|
|
1496
|
-
/**
|
|
1529
|
+
/** Событие активации любой даты */
|
|
1497
1530
|
this.pickerDateTimeChange = new EventEmitter();
|
|
1498
1531
|
}
|
|
1499
1532
|
ngOnInit() {
|
|
@@ -1514,19 +1547,19 @@ class OwlMonthViewComponent {
|
|
|
1514
1547
|
this.localeSub.unsubscribe();
|
|
1515
1548
|
}
|
|
1516
1549
|
/**
|
|
1517
|
-
*
|
|
1550
|
+
* Обрабатывает выбор ячейки календаря
|
|
1518
1551
|
*/
|
|
1519
1552
|
selectCalendarCell(cell) {
|
|
1520
|
-
//
|
|
1521
|
-
// 1
|
|
1522
|
-
// 2
|
|
1553
|
+
// Условия, при которых дата не выбирается:
|
|
1554
|
+
// 1) Ячейка календаря недоступна для выбора
|
|
1555
|
+
// 2) Дата находится вне текущего месяца и включён hideOtherMonths
|
|
1523
1556
|
if (!cell.enabled || (this.hideOtherMonths && cell.out)) {
|
|
1524
1557
|
return;
|
|
1525
1558
|
}
|
|
1526
1559
|
this.selectDate(cell.value);
|
|
1527
1560
|
}
|
|
1528
1561
|
/**
|
|
1529
|
-
*
|
|
1562
|
+
* Обрабатывает выбор новой даты
|
|
1530
1563
|
*/
|
|
1531
1564
|
selectDate(date) {
|
|
1532
1565
|
const daysDiff = date - 1;
|
|
@@ -1535,59 +1568,59 @@ class OwlMonthViewComponent {
|
|
|
1535
1568
|
this.userSelection.emit();
|
|
1536
1569
|
}
|
|
1537
1570
|
/**
|
|
1538
|
-
*
|
|
1571
|
+
* Обрабатывает keydown в таблице календаря
|
|
1539
1572
|
*/
|
|
1540
1573
|
handleCalendarKeydown(event) {
|
|
1541
1574
|
let dateTime;
|
|
1542
1575
|
switch (event.keyCode) {
|
|
1543
|
-
//
|
|
1576
|
+
// На один день назад
|
|
1544
1577
|
case LEFT_ARROW:
|
|
1545
1578
|
dateTime = this.dateTimeAdapter.addCalendarDays(this.pickerDateTime, -1);
|
|
1546
1579
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1547
1580
|
break;
|
|
1548
|
-
//
|
|
1581
|
+
// На один день вперёд
|
|
1549
1582
|
case RIGHT_ARROW:
|
|
1550
1583
|
dateTime = this.dateTimeAdapter.addCalendarDays(this.pickerDateTime, 1);
|
|
1551
1584
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1552
1585
|
break;
|
|
1553
|
-
//
|
|
1586
|
+
// На одну неделю назад
|
|
1554
1587
|
case UP_ARROW:
|
|
1555
1588
|
dateTime = this.dateTimeAdapter.addCalendarDays(this.pickerDateTime, -7);
|
|
1556
1589
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1557
1590
|
break;
|
|
1558
|
-
//
|
|
1591
|
+
// На одну неделю вперёд
|
|
1559
1592
|
case DOWN_ARROW:
|
|
1560
1593
|
dateTime = this.dateTimeAdapter.addCalendarDays(this.pickerDateTime, 7);
|
|
1561
1594
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1562
1595
|
break;
|
|
1563
|
-
//
|
|
1596
|
+
// К первому дню текущего месяца
|
|
1564
1597
|
case HOME:
|
|
1565
1598
|
dateTime = this.dateTimeAdapter.addCalendarDays(this.pickerDateTime, 1 - this.dateTimeAdapter.getDate(this.pickerDateTime));
|
|
1566
1599
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1567
1600
|
break;
|
|
1568
|
-
//
|
|
1601
|
+
// К последнему дню текущего месяца
|
|
1569
1602
|
case END:
|
|
1570
1603
|
dateTime = this.dateTimeAdapter.addCalendarDays(this.pickerDateTime, this.dateTimeAdapter.getNumDaysInMonth(this.pickerDateTime) -
|
|
1571
1604
|
this.dateTimeAdapter.getDate(this.pickerDateTime));
|
|
1572
1605
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1573
1606
|
break;
|
|
1574
|
-
//
|
|
1607
|
+
// На один месяц (или год) назад
|
|
1575
1608
|
case PAGE_UP:
|
|
1576
1609
|
dateTime = event.altKey
|
|
1577
1610
|
? this.dateTimeAdapter.addCalendarYears(this.pickerDateTime, -1)
|
|
1578
1611
|
: this.dateTimeAdapter.addCalendarMonths(this.pickerDateTime, -1);
|
|
1579
1612
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1580
1613
|
break;
|
|
1581
|
-
//
|
|
1614
|
+
// На один месяц (или год) вперёд
|
|
1582
1615
|
case PAGE_DOWN:
|
|
1583
1616
|
dateTime = event.altKey
|
|
1584
1617
|
? this.dateTimeAdapter.addCalendarYears(this.pickerDateTime, 1)
|
|
1585
1618
|
: this.dateTimeAdapter.addCalendarMonths(this.pickerDateTime, 1);
|
|
1586
1619
|
this.pickerDateTimeChange.emit(dateTime);
|
|
1587
1620
|
break;
|
|
1588
|
-
//
|
|
1621
|
+
// Выбирает активную дату
|
|
1589
1622
|
case ENTER:
|
|
1590
|
-
if (
|
|
1623
|
+
if (this.isDateEnabled(this.dateTimeAdapter.addCalendarDays(this.firstDateOfMonth, this.dateTimeAdapter.getDate(this.pickerDateTime) - 1))) {
|
|
1591
1624
|
this.selectDate(this.dateTimeAdapter.getDate(this.pickerDateTime));
|
|
1592
1625
|
}
|
|
1593
1626
|
break;
|
|
@@ -1598,7 +1631,7 @@ class OwlMonthViewComponent {
|
|
|
1598
1631
|
event.preventDefault();
|
|
1599
1632
|
}
|
|
1600
1633
|
/**
|
|
1601
|
-
*
|
|
1634
|
+
* Создаёт массив дней недели для календаря
|
|
1602
1635
|
* */
|
|
1603
1636
|
generateWeekDays() {
|
|
1604
1637
|
const longWeekdays = this.dateTimeAdapter.getDayOfWeekNames('long');
|
|
@@ -1615,10 +1648,10 @@ class OwlMonthViewComponent {
|
|
|
1615
1648
|
return;
|
|
1616
1649
|
}
|
|
1617
1650
|
/**
|
|
1618
|
-
*
|
|
1651
|
+
* Создаёт массив дней календаря
|
|
1619
1652
|
* */
|
|
1620
1653
|
generateCalendar() {
|
|
1621
|
-
if (
|
|
1654
|
+
if (this.pickerDateTime == null) {
|
|
1622
1655
|
return;
|
|
1623
1656
|
}
|
|
1624
1657
|
this.todayDate = null;
|
|
@@ -1652,11 +1685,11 @@ class OwlMonthViewComponent {
|
|
|
1652
1685
|
}
|
|
1653
1686
|
getISOWeek(d) {
|
|
1654
1687
|
const clonedDate = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
|
|
1655
|
-
//
|
|
1688
|
+
// Используем для воскресенья номер дня 7
|
|
1656
1689
|
clonedDate.setUTCDate(clonedDate.getUTCDate() + 4 - (clonedDate.getUTCDay() || 7));
|
|
1657
|
-
//
|
|
1690
|
+
// Получаем первый день года
|
|
1658
1691
|
const yearStart = new Date(Date.UTC(clonedDate.getUTCFullYear(), 0, 1));
|
|
1659
|
-
//
|
|
1692
|
+
// Вычисляем число полных недель до ближайшего четверга
|
|
1660
1693
|
const weekNo = Math.ceil((((+clonedDate - +yearStart) / 86400000) + 1) / 7);
|
|
1661
1694
|
return weekNo;
|
|
1662
1695
|
}
|
|
@@ -1671,36 +1704,36 @@ class OwlMonthViewComponent {
|
|
|
1671
1704
|
}
|
|
1672
1705
|
}
|
|
1673
1706
|
/**
|
|
1674
|
-
*
|
|
1707
|
+
* Создаёт CalendarCell для дней
|
|
1675
1708
|
*/
|
|
1676
1709
|
createDateCell(date, daysDiff) {
|
|
1677
|
-
//
|
|
1710
|
+
// Количество дней в месяце
|
|
1678
1711
|
const daysInMonth = this.dateTimeAdapter.getNumDaysInMonth(this.pickerDateTime);
|
|
1679
1712
|
const dateNum = this.dateTimeAdapter.getDate(date);
|
|
1680
1713
|
// const dateName = this.dateNames[dateNum - 1];
|
|
1681
1714
|
const dateName = dateNum.toString();
|
|
1682
1715
|
const ariaLabel = this.dateTimeAdapter.format(date, this.dateTimeFormats.dateA11yLabel);
|
|
1683
|
-
//
|
|
1716
|
+
// Проверяем доступность даты для выбора
|
|
1684
1717
|
const enabled = this.isDateEnabled(date);
|
|
1685
|
-
//
|
|
1718
|
+
// Проверяем, находится ли дата вне текущего месяца
|
|
1686
1719
|
const dayValue = daysDiff + 1;
|
|
1687
1720
|
const out = dayValue < 1 || dayValue > daysInMonth;
|
|
1688
1721
|
const cellClass = 'owl-dt-day-' + this.dateTimeAdapter.getDay(date);
|
|
1689
1722
|
return new CalendarCell(dayValue, dateName, ariaLabel, enabled, out, cellClass);
|
|
1690
1723
|
}
|
|
1691
1724
|
/**
|
|
1692
|
-
*
|
|
1725
|
+
* Проверяет допустимость даты
|
|
1693
1726
|
*/
|
|
1694
1727
|
isDateEnabled(date) {
|
|
1695
|
-
return (
|
|
1728
|
+
return (date != null &&
|
|
1696
1729
|
(!this.dateFilter || this.dateFilter(date)) &&
|
|
1697
|
-
(
|
|
1730
|
+
(this.minDate == null ||
|
|
1698
1731
|
this.dateTimeAdapter.compare(date, this.minDate) >= 0) &&
|
|
1699
|
-
(
|
|
1732
|
+
(this.maxDate == null ||
|
|
1700
1733
|
this.dateTimeAdapter.compare(date, this.maxDate) <= 0));
|
|
1701
1734
|
}
|
|
1702
1735
|
/**
|
|
1703
|
-
*
|
|
1736
|
+
* Возвращает корректный объект даты
|
|
1704
1737
|
*/
|
|
1705
1738
|
getValidDate(obj) {
|
|
1706
1739
|
return this.dateTimeAdapter.isDateInstance(obj) &&
|
|
@@ -1709,11 +1742,11 @@ class OwlMonthViewComponent {
|
|
|
1709
1742
|
: null;
|
|
1710
1743
|
}
|
|
1711
1744
|
/**
|
|
1712
|
-
*
|
|
1745
|
+
* Проверяет, что даты не равны null и находятся в одном месяце
|
|
1713
1746
|
*/
|
|
1714
1747
|
isSameMonth(dateLeft, dateRight) {
|
|
1715
|
-
return (dateLeft &&
|
|
1716
|
-
dateRight &&
|
|
1748
|
+
return (dateLeft != null &&
|
|
1749
|
+
dateRight != null &&
|
|
1717
1750
|
this.dateTimeAdapter.isValid(dateLeft) &&
|
|
1718
1751
|
this.dateTimeAdapter.isValid(dateRight) &&
|
|
1719
1752
|
this.dateTimeAdapter.getYear(dateLeft) ===
|
|
@@ -1728,16 +1761,16 @@ class OwlMonthViewComponent {
|
|
|
1728
1761
|
return Math.ceil((((+jsDate - +yearStart) / 86400000) + 1) / 7);
|
|
1729
1762
|
}
|
|
1730
1763
|
/**
|
|
1731
|
-
*
|
|
1732
|
-
*
|
|
1733
|
-
*
|
|
1764
|
+
* Задаёт значение selectedDates
|
|
1765
|
+
* В режиме single содержит одно значение — выбранную дату
|
|
1766
|
+
* В режиме range содержит два значения: fromValue и toValue
|
|
1734
1767
|
* */
|
|
1735
1768
|
setSelectedDates() {
|
|
1736
1769
|
this.selectedDates = [];
|
|
1737
|
-
if (
|
|
1770
|
+
if (this.firstDateOfMonth == null) {
|
|
1738
1771
|
return;
|
|
1739
1772
|
}
|
|
1740
|
-
if (this.isInSingleMode && this.selected) {
|
|
1773
|
+
if (this.isInSingleMode && this.selected != null) {
|
|
1741
1774
|
const dayDiff = this.dateTimeAdapter.differenceInCalendarDays(this.selected, this.firstDateOfMonth);
|
|
1742
1775
|
this.selectedDates[0] = dayDiff + 1;
|
|
1743
1776
|
return;
|
|
@@ -1813,7 +1846,7 @@ class OwlCalendarComponent {
|
|
|
1813
1846
|
set minDate(value) {
|
|
1814
1847
|
value = this.dateTimeAdapter.deserialize(value);
|
|
1815
1848
|
value = this.getValidDate(value);
|
|
1816
|
-
this._minDate = value
|
|
1849
|
+
this._minDate = value != null
|
|
1817
1850
|
? this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(value), this.dateTimeAdapter.getMonth(value), this.dateTimeAdapter.getDate(value))
|
|
1818
1851
|
: null;
|
|
1819
1852
|
}
|
|
@@ -1823,7 +1856,7 @@ class OwlCalendarComponent {
|
|
|
1823
1856
|
set maxDate(value) {
|
|
1824
1857
|
value = this.dateTimeAdapter.deserialize(value);
|
|
1825
1858
|
value = this.getValidDate(value);
|
|
1826
|
-
this._maxDate = value
|
|
1859
|
+
this._maxDate = value != null
|
|
1827
1860
|
? this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(value), this.dateTimeAdapter.getMonth(value), this.dateTimeAdapter.getDate(value))
|
|
1828
1861
|
: null;
|
|
1829
1862
|
}
|
|
@@ -1833,7 +1866,7 @@ class OwlCalendarComponent {
|
|
|
1833
1866
|
set pickerDateTime(value) {
|
|
1834
1867
|
value = this.dateTimeAdapter.deserialize(value);
|
|
1835
1868
|
this._pickerDateTime =
|
|
1836
|
-
this.getValidDate(value)
|
|
1869
|
+
this.getValidDate(value) ?? this.dateTimeAdapter.now();
|
|
1837
1870
|
}
|
|
1838
1871
|
get selected() {
|
|
1839
1872
|
return this._selected;
|
|
@@ -1846,7 +1879,7 @@ class OwlCalendarComponent {
|
|
|
1846
1879
|
return this._selecteds;
|
|
1847
1880
|
}
|
|
1848
1881
|
set selecteds(values) {
|
|
1849
|
-
this._selecteds = values.map(v => {
|
|
1882
|
+
this._selecteds = (values ?? []).map(v => {
|
|
1850
1883
|
v = this.dateTimeAdapter.deserialize(v);
|
|
1851
1884
|
return this.getValidDate(v);
|
|
1852
1885
|
});
|
|
@@ -1905,7 +1938,7 @@ class OwlCalendarComponent {
|
|
|
1905
1938
|
return this._currentView === DateView.MONTH;
|
|
1906
1939
|
}
|
|
1907
1940
|
/**
|
|
1908
|
-
*
|
|
1941
|
+
* Добавляет класс 'owl-dt-calendar' к элементу компонента
|
|
1909
1942
|
* */
|
|
1910
1943
|
get owlDTCalendarClass() {
|
|
1911
1944
|
return true;
|
|
@@ -1917,56 +1950,58 @@ class OwlCalendarComponent {
|
|
|
1917
1950
|
this.cdRef = cdRef;
|
|
1918
1951
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
1919
1952
|
this.dateTimeFormats = dateTimeFormats;
|
|
1953
|
+
this.injector = inject(Injector);
|
|
1954
|
+
this.destroyRef = inject(DestroyRef);
|
|
1920
1955
|
this.DateView = DateView;
|
|
1921
1956
|
this._selecteds = [];
|
|
1922
1957
|
/**
|
|
1923
|
-
*
|
|
1958
|
+
* Начальное представление календаря
|
|
1924
1959
|
*/
|
|
1925
1960
|
this.startView = DateView.MONTH;
|
|
1926
1961
|
/**
|
|
1927
|
-
*
|
|
1962
|
+
* Нужно ли показывать только представления года и нескольких лет
|
|
1928
1963
|
*/
|
|
1929
1964
|
this.yearOnly = false;
|
|
1930
1965
|
/**
|
|
1931
|
-
*
|
|
1966
|
+
* Нужно ли показывать номера недель в календаре
|
|
1932
1967
|
* */
|
|
1933
1968
|
this.showCalendarWeeks = false;
|
|
1934
1969
|
/**
|
|
1935
|
-
*
|
|
1970
|
+
* Нужно ли показывать только представление нескольких лет
|
|
1936
1971
|
*/
|
|
1937
1972
|
this.multiyearOnly = false;
|
|
1938
|
-
/**
|
|
1973
|
+
/** Событие изменения отображаемых даты и времени */
|
|
1939
1974
|
this.pickerDateTimeChange = new EventEmitter();
|
|
1940
|
-
/**
|
|
1975
|
+
/** Событие изменения выбранной даты */
|
|
1941
1976
|
this.dateClicked = new EventEmitter();
|
|
1942
|
-
/**
|
|
1977
|
+
/** Событие изменения текущей выбранной даты */
|
|
1943
1978
|
this.selectedChange = new EventEmitter();
|
|
1944
|
-
/**
|
|
1979
|
+
/** Событие выбора любой даты */
|
|
1945
1980
|
this.userSelection = new EventEmitter();
|
|
1946
1981
|
/**
|
|
1947
|
-
*
|
|
1982
|
+
* Передаёт выбранный год, не изменяя выбранную дату
|
|
1948
1983
|
* */
|
|
1949
1984
|
this.yearSelected = new EventEmitter();
|
|
1950
1985
|
/**
|
|
1951
|
-
*
|
|
1986
|
+
* Передаёт выбранный месяц, не изменяя выбранную дату
|
|
1952
1987
|
* */
|
|
1953
1988
|
this.monthSelected = new EventEmitter();
|
|
1954
1989
|
this.intlChangesSub = Subscription.EMPTY;
|
|
1955
1990
|
/**
|
|
1956
|
-
*
|
|
1957
|
-
*
|
|
1958
|
-
*
|
|
1991
|
+
* Откладывает перевод фокуса на активную ячейку до следующего обновления представления
|
|
1992
|
+
* Перевод фокуса откладывается, чтобы дождаться, пока Angular
|
|
1993
|
+
* обновит дочерние элементы представления
|
|
1959
1994
|
*/
|
|
1960
1995
|
this.moveFocusOnNextTick = false;
|
|
1961
1996
|
/**
|
|
1962
|
-
*
|
|
1997
|
+
* Фильтр дат для представлений месяца и года
|
|
1963
1998
|
*/
|
|
1964
1999
|
this.dateFilterForViews = (date) => {
|
|
1965
|
-
return (
|
|
2000
|
+
return (date != null &&
|
|
1966
2001
|
(!this.dateFilter || this.dateFilter(date)) &&
|
|
1967
|
-
(
|
|
2002
|
+
(this.minDate == null ||
|
|
1968
2003
|
this.dateTimeAdapter.compare(date, this.minDate) >= 0) &&
|
|
1969
|
-
(
|
|
2004
|
+
(this.maxDate == null ||
|
|
1970
2005
|
this.dateTimeAdapter.compare(date, this.maxDate) <= 0));
|
|
1971
2006
|
};
|
|
1972
2007
|
this.intlChangesSub = this.pickerIntl.changes.subscribe(() => {
|
|
@@ -1988,7 +2023,7 @@ class OwlCalendarComponent {
|
|
|
1988
2023
|
this.intlChangesSub.unsubscribe();
|
|
1989
2024
|
}
|
|
1990
2025
|
/**
|
|
1991
|
-
*
|
|
2026
|
+
* Переключает представления месяца и года
|
|
1992
2027
|
*/
|
|
1993
2028
|
toggleViews() {
|
|
1994
2029
|
let nextView = null;
|
|
@@ -2009,7 +2044,7 @@ class OwlCalendarComponent {
|
|
|
2009
2044
|
this.currentView = nextView;
|
|
2010
2045
|
}
|
|
2011
2046
|
/**
|
|
2012
|
-
*
|
|
2047
|
+
* Обрабатывает нажатие кнопки перехода к предыдущему периоду
|
|
2013
2048
|
* */
|
|
2014
2049
|
previousClicked() {
|
|
2015
2050
|
this.pickerDateTime = this.isMonthView
|
|
@@ -2018,7 +2053,7 @@ class OwlCalendarComponent {
|
|
|
2018
2053
|
this.pickerDateTimeChange.emit(this.pickerDateTime);
|
|
2019
2054
|
}
|
|
2020
2055
|
/**
|
|
2021
|
-
*
|
|
2056
|
+
* Обрабатывает нажатие кнопки перехода к следующему периоду
|
|
2022
2057
|
* */
|
|
2023
2058
|
nextClicked() {
|
|
2024
2059
|
this.pickerDateTime = this.isMonthView
|
|
@@ -2038,7 +2073,7 @@ class OwlCalendarComponent {
|
|
|
2038
2073
|
}*/
|
|
2039
2074
|
}
|
|
2040
2075
|
/**
|
|
2041
|
-
*
|
|
2076
|
+
* Меняет отображаемую дату и переключается на указанное представление
|
|
2042
2077
|
*/
|
|
2043
2078
|
goToDateInView(date, view) {
|
|
2044
2079
|
this.handlePickerDateTimeChange(date);
|
|
@@ -2053,7 +2088,7 @@ class OwlCalendarComponent {
|
|
|
2053
2088
|
return;
|
|
2054
2089
|
}
|
|
2055
2090
|
/**
|
|
2056
|
-
*
|
|
2091
|
+
* Меняет отображаемую дату
|
|
2057
2092
|
*/
|
|
2058
2093
|
handlePickerDateTimeChange(date) {
|
|
2059
2094
|
this.pickerDateTime = this.dateTimeAdapter.clampDate(date, this.minDate, this.maxDate);
|
|
@@ -2064,31 +2099,31 @@ class OwlCalendarComponent {
|
|
|
2064
2099
|
this.userSelection.emit();
|
|
2065
2100
|
}
|
|
2066
2101
|
/**
|
|
2067
|
-
*
|
|
2102
|
+
* Доступна ли кнопка перехода к предыдущему периоду
|
|
2068
2103
|
*/
|
|
2069
2104
|
prevButtonEnabled() {
|
|
2070
|
-
return (
|
|
2105
|
+
return (this.minDate == null || !this.isSameView(this.pickerDateTime, this.minDate));
|
|
2071
2106
|
}
|
|
2072
2107
|
/**
|
|
2073
|
-
*
|
|
2108
|
+
* Доступна ли кнопка перехода к следующему периоду
|
|
2074
2109
|
*/
|
|
2075
2110
|
nextButtonEnabled() {
|
|
2076
|
-
return (
|
|
2111
|
+
return (this.maxDate == null || !this.isSameView(this.pickerDateTime, this.maxDate));
|
|
2077
2112
|
}
|
|
2078
2113
|
/**
|
|
2079
|
-
*
|
|
2114
|
+
* Переводит фокус на элемент компонента
|
|
2080
2115
|
* */
|
|
2081
2116
|
focusActiveCell() {
|
|
2082
|
-
this.
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
}
|
|
2091
|
-
});
|
|
2117
|
+
if (this.destroyRef.destroyed) {
|
|
2118
|
+
return;
|
|
2119
|
+
}
|
|
2120
|
+
this.focusRef?.destroy();
|
|
2121
|
+
this.focusRef = afterNextRender({
|
|
2122
|
+
write: () => {
|
|
2123
|
+
this.focusRef = undefined;
|
|
2124
|
+
this.elmRef.nativeElement.querySelector('.owl-dt-calendar-cell-active')?.focus();
|
|
2125
|
+
}
|
|
2126
|
+
}, { injector: this.injector });
|
|
2092
2127
|
}
|
|
2093
2128
|
selectYearInMultiYearView(normalizedYear) {
|
|
2094
2129
|
this.yearSelected.emit(normalizedYear);
|
|
@@ -2097,20 +2132,20 @@ class OwlCalendarComponent {
|
|
|
2097
2132
|
this.monthSelected.emit(normalizedMonth);
|
|
2098
2133
|
}
|
|
2099
2134
|
/**
|
|
2100
|
-
*
|
|
2135
|
+
* Соответствуют ли две даты одному представлению в текущем режиме (месяц или год)
|
|
2101
2136
|
*/
|
|
2102
2137
|
isSameView(date1, date2) {
|
|
2103
2138
|
if (this._currentView === DateView.MONTH) {
|
|
2104
|
-
return !!(date1 &&
|
|
2105
|
-
date2 &&
|
|
2139
|
+
return !!(date1 != null &&
|
|
2140
|
+
date2 != null &&
|
|
2106
2141
|
this.dateTimeAdapter.getYear(date1) ===
|
|
2107
2142
|
this.dateTimeAdapter.getYear(date2) &&
|
|
2108
2143
|
this.dateTimeAdapter.getMonth(date1) ===
|
|
2109
2144
|
this.dateTimeAdapter.getMonth(date2));
|
|
2110
2145
|
}
|
|
2111
2146
|
else if (this._currentView === DateView.YEAR) {
|
|
2112
|
-
return !!(date1 &&
|
|
2113
|
-
date2 &&
|
|
2147
|
+
return !!(date1 != null &&
|
|
2148
|
+
date2 != null &&
|
|
2114
2149
|
this.dateTimeAdapter.getYear(date1) ===
|
|
2115
2150
|
this.dateTimeAdapter.getYear(date2));
|
|
2116
2151
|
}
|
|
@@ -2119,7 +2154,7 @@ class OwlCalendarComponent {
|
|
|
2119
2154
|
}
|
|
2120
2155
|
}
|
|
2121
2156
|
/**
|
|
2122
|
-
*
|
|
2157
|
+
* Возвращает корректный объект даты
|
|
2123
2158
|
*/
|
|
2124
2159
|
getValidDate(obj) {
|
|
2125
2160
|
return this.dateTimeAdapter.isDateInstance(obj) &&
|
|
@@ -2128,13 +2163,13 @@ class OwlCalendarComponent {
|
|
|
2128
2163
|
: null;
|
|
2129
2164
|
}
|
|
2130
2165
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlCalendarComponent, deps: [{ token: i0.ElementRef }, { token: OwlDateTimeIntl }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: DateTimeAdapter, optional: true }, { token: OWL_DATE_TIME_FORMATS, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2131
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: OwlCalendarComponent, isStandalone: false, selector: "owl-date-time-calendar", inputs: { minDate: "minDate", maxDate: "maxDate", pickerDateTime: "pickerDateTime", selected: "selected", selecteds: "selecteds", dateFilter: "dateFilter", firstDayOfWeek: "firstDayOfWeek", selectMode: "selectMode", startView: "startView", yearOnly: "yearOnly", showCalendarWeeks: "showCalendarWeeks", multiyearOnly: "multiyearOnly", hideOtherMonths: "hideOtherMonths" }, outputs: { pickerDateTimeChange: "pickerDateTimeChange", dateClicked: "dateClicked", selectedChange: "selectedChange", userSelection: "userSelection", yearSelected: "yearSelected", monthSelected: "monthSelected" }, host: { properties: { "class.owl-dt-calendar": "owlDTCalendarClass" } }, exportAs: ["owlDateTimeCalendar"], ngImport: i0, template: "<div class=\"owl-dt-calendar-control\">\r\n <!-- focus when keyboard tab (http://kizu.ru/en/blog/keyboard-only-focus/#x) -->\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [style.visibility]=\"showControlArrows ? 'visible' : 'hidden'\"\r\n [disabled]=\"!prevButtonEnabled()\"\r\n [attr.aria-label]=\"prevButtonLabel\"\r\n (click)=\"previousClicked()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n <!-- <editor-fold desc=\"SVG Arrow Left\"> -->\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 250.738 250.738\"\r\n style=\"enable-background: new 0 0 250.738 250.738\"\r\n xml:space=\"preserve\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n >\r\n <path\r\n style=\"fill-rule: evenodd; clip-rule: evenodd\"\r\n d=\"M96.633,125.369l95.053-94.533c7.101-7.055,7.101-18.492,0-25.546 c-7.1-7.054-18.613-7.054-25.714,0L58.989,111.689c-3.784,3.759-5.487,8.759-5.238,13.68c-0.249,4.922,1.454,9.921,5.238,13.681 l106.983,106.398c7.101,7.055,18.613,7.055,25.714,0c7.101-7.054,7.101-18.491,0-25.544L96.633,125.369z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </button>\r\n <div class=\"owl-dt-calendar-control-content\">\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-period-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-label]=\"periodButtonLabel\"\r\n (click)=\"toggleViews()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n {{ periodButtonText }}\r\n\r\n <span\r\n class=\"owl-dt-control-button-arrow\"\r\n [style.transform]=\"\r\n 'rotate(' + (isMonthView ? 0 : 180) + 'deg)'\r\n \"\r\n >\r\n <!-- <editor-fold desc=\"SVG Arrow\"> -->\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n width=\"50%\"\r\n height=\"50%\"\r\n viewBox=\"0 0 292.362 292.362\"\r\n style=\"enable-background: new 0 0 292.362 292.362\"\r\n xml:space=\"preserve\"\r\n >\r\n <g>\r\n <path\r\n d=\"M286.935,69.377c-3.614-3.617-7.898-5.424-12.848-5.424H18.274c-4.952,0-9.233,1.807-12.85,5.424\r\n C1.807,72.998,0,77.279,0,82.228c0,4.948,1.807,9.229,5.424,12.847l127.907,127.907c3.621,3.617,7.902,5.428,12.85,5.428\r\n s9.233-1.811,12.847-5.428L286.935,95.074c3.613-3.617,5.427-7.898,5.427-12.847C292.362,77.279,290.548,72.998,286.935,69.377z\"\r\n />\r\n </g>\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </span>\r\n </button>\r\n </div>\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [style.visibility]=\"showControlArrows ? 'visible' : 'hidden'\"\r\n [disabled]=\"!nextButtonEnabled()\"\r\n [attr.aria-label]=\"nextButtonLabel\"\r\n (click)=\"nextClicked()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n <!-- <editor-fold desc=\"SVG Arrow Right\"> -->\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 250.738 250.738\"\r\n style=\"enable-background: new 0 0 250.738 250.738\"\r\n xml:space=\"preserve\"\r\n >\r\n <path\r\n style=\"fill-rule: evenodd; clip-rule: evenodd\"\r\n d=\"M191.75,111.689L84.766,5.291c-7.1-7.055-18.613-7.055-25.713,0\r\n c-7.101,7.054-7.101,18.49,0,25.544l95.053,94.534l-95.053,94.533c-7.101,7.054-7.101,18.491,0,25.545\r\n c7.1,7.054,18.613,7.054,25.713,0L191.75,139.05c3.784-3.759,5.487-8.759,5.238-13.681\r\n C197.237,120.447,195.534,115.448,191.75,111.689z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </button>\r\n</div>\r\n<div class=\"owl-dt-calendar-main\" cdkMonitorSubtreeFocus tabindex=\"-1\">\r\n @switch (currentView) {\r\n @case (DateView.MONTH) {\r\n <owl-date-time-month-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [firstDayOfWeek]=\"firstDayOfWeek\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [showCalendarWeeks]=\"showCalendarWeeks\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n [hideOtherMonths]=\"hideOtherMonths\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (selectedChange)=\"dateSelected($event)\"\r\n (userSelection)=\"userSelected()\"\r\n ></owl-date-time-month-view>\r\n }\r\n @case (DateView.YEAR) {\r\n <owl-date-time-year-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n (keyboardEnter)=\"focusActiveCell()\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (monthSelected)=\"selectMonthInYearView($event)\"\r\n (change)=\"goToDateInView($event, DateView.MONTH)\"\r\n ></owl-date-time-year-view>\r\n }\r\n @case (DateView.MULTI_YEARS) {\r\n <owl-date-time-multi-year-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n (keyboardEnter)=\"focusActiveCell()\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (yearSelected)=\"selectYearInMultiYearView($event)\"\r\n (change)=\"goToDateInView($event, DateView.YEAR)\"\r\n ></owl-date-time-multi-year-view>\r\n }\r\n }\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "directive", type: i1.CdkMonitorFocus, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: ["cdkFocusChange"], exportAs: ["cdkMonitorFocus"] }, { kind: "component", type: OwlMultiYearViewComponent, selector: "owl-date-time-multi-year-view", inputs: ["selectMode", "selected", "selecteds", "pickerDateTime", "dateFilter", "minDate", "maxDate"], outputs: ["change", "yearSelected", "pickerDateTimeChange", "keyboardEnter"] }, { kind: "component", type: OwlYearViewComponent, selector: "owl-date-time-year-view", inputs: ["selectMode", "selected", "selecteds", "pickerDateTime", "dateFilter", "minDate", "maxDate"], outputs: ["change", "monthSelected", "pickerDateTimeChange", "keyboardEnter"], exportAs: ["owlMonthView"] }, { kind: "component", type: OwlMonthViewComponent, selector: "owl-date-time-month-view", inputs: ["hideOtherMonths", "showCalendarWeeks", "firstDayOfWeek", "selectMode", "selected", "selecteds", "pickerDateTime", "dateFilter", "minDate", "maxDate"], outputs: ["selectedChange", "userSelection", "pickerDateTimeChange"], exportAs: ["owlYearView"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2166
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: OwlCalendarComponent, isStandalone: false, selector: "owl-date-time-calendar", inputs: { minDate: "minDate", maxDate: "maxDate", pickerDateTime: "pickerDateTime", selected: "selected", selecteds: "selecteds", dateFilter: "dateFilter", firstDayOfWeek: "firstDayOfWeek", selectMode: "selectMode", startView: "startView", yearOnly: "yearOnly", showCalendarWeeks: "showCalendarWeeks", multiyearOnly: "multiyearOnly", hideOtherMonths: "hideOtherMonths" }, outputs: { pickerDateTimeChange: "pickerDateTimeChange", dateClicked: "dateClicked", selectedChange: "selectedChange", userSelection: "userSelection", yearSelected: "yearSelected", monthSelected: "monthSelected" }, host: { properties: { "class.owl-dt-calendar": "owlDTCalendarClass" } }, exportAs: ["owlDateTimeCalendar"], ngImport: i0, template: "<div class=\"owl-dt-calendar-control\">\r\n <!-- \u0424\u043E\u043A\u0443\u0441 \u043F\u0440\u0438 \u043D\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043A\u043B\u0430\u0432\u0438\u0448\u0435\u0439 Tab (http://kizu.ru/en/blog/keyboard-only-focus/#x) -->\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [style.visibility]=\"showControlArrows ? 'visible' : 'hidden'\"\r\n [disabled]=\"!prevButtonEnabled()\"\r\n [attr.aria-label]=\"prevButtonLabel\"\r\n (click)=\"previousClicked()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043B\u0435\u0432\u043E\"> -->\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 250.738 250.738\"\r\n style=\"enable-background: new 0 0 250.738 250.738\"\r\n xml:space=\"preserve\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n >\r\n <path\r\n style=\"fill-rule: evenodd; clip-rule: evenodd\"\r\n d=\"M96.633,125.369l95.053-94.533c7.101-7.055,7.101-18.492,0-25.546 c-7.1-7.054-18.613-7.054-25.714,0L58.989,111.689c-3.784,3.759-5.487,8.759-5.238,13.68c-0.249,4.922,1.454,9.921,5.238,13.681 l106.983,106.398c7.101,7.055,18.613,7.055,25.714,0c7.101-7.054,7.101-18.491,0-25.544L96.633,125.369z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </button>\r\n <div class=\"owl-dt-calendar-control-content\">\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-period-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-label]=\"periodButtonLabel\"\r\n (click)=\"toggleViews()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n {{ periodButtonText }}\r\n\r\n <span\r\n class=\"owl-dt-control-button-arrow\"\r\n [style.transform]=\"\r\n 'rotate(' + (isMonthView ? 0 : 180) + 'deg)'\r\n \"\r\n >\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430\"> -->\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n width=\"50%\"\r\n height=\"50%\"\r\n viewBox=\"0 0 292.362 292.362\"\r\n style=\"enable-background: new 0 0 292.362 292.362\"\r\n xml:space=\"preserve\"\r\n >\r\n <g>\r\n <path\r\n d=\"M286.935,69.377c-3.614-3.617-7.898-5.424-12.848-5.424H18.274c-4.952,0-9.233,1.807-12.85,5.424\r\n C1.807,72.998,0,77.279,0,82.228c0,4.948,1.807,9.229,5.424,12.847l127.907,127.907c3.621,3.617,7.902,5.428,12.85,5.428\r\n s9.233-1.811,12.847-5.428L286.935,95.074c3.613-3.617,5.427-7.898,5.427-12.847C292.362,77.279,290.548,72.998,286.935,69.377z\"\r\n />\r\n </g>\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </span>\r\n </button>\r\n </div>\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [style.visibility]=\"showControlArrows ? 'visible' : 'hidden'\"\r\n [disabled]=\"!nextButtonEnabled()\"\r\n [attr.aria-label]=\"nextButtonLabel\"\r\n (click)=\"nextClicked()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043F\u0440\u0430\u0432\u043E\"> -->\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 250.738 250.738\"\r\n style=\"enable-background: new 0 0 250.738 250.738\"\r\n xml:space=\"preserve\"\r\n >\r\n <path\r\n style=\"fill-rule: evenodd; clip-rule: evenodd\"\r\n d=\"M191.75,111.689L84.766,5.291c-7.1-7.055-18.613-7.055-25.713,0\r\n c-7.101,7.054-7.101,18.49,0,25.544l95.053,94.534l-95.053,94.533c-7.101,7.054-7.101,18.491,0,25.545\r\n c7.1,7.054,18.613,7.054,25.713,0L191.75,139.05c3.784-3.759,5.487-8.759,5.238-13.681\r\n C197.237,120.447,195.534,115.448,191.75,111.689z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </button>\r\n</div>\r\n<div class=\"owl-dt-calendar-main\" cdkMonitorSubtreeFocus tabindex=\"-1\">\r\n @switch (currentView) {\r\n @case (DateView.MONTH) {\r\n <owl-date-time-month-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [firstDayOfWeek]=\"firstDayOfWeek\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [showCalendarWeeks]=\"showCalendarWeeks\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n [hideOtherMonths]=\"hideOtherMonths\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (selectedChange)=\"dateSelected($event)\"\r\n (userSelection)=\"userSelected()\"\r\n ></owl-date-time-month-view>\r\n }\r\n @case (DateView.YEAR) {\r\n <owl-date-time-year-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n (keyboardEnter)=\"focusActiveCell()\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (monthSelected)=\"selectMonthInYearView($event)\"\r\n (change)=\"goToDateInView($event, DateView.MONTH)\"\r\n ></owl-date-time-year-view>\r\n }\r\n @case (DateView.MULTI_YEARS) {\r\n <owl-date-time-multi-year-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n (keyboardEnter)=\"focusActiveCell()\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (yearSelected)=\"selectYearInMultiYearView($event)\"\r\n (change)=\"goToDateInView($event, DateView.YEAR)\"\r\n ></owl-date-time-multi-year-view>\r\n }\r\n }\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "directive", type: i1.CdkMonitorFocus, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: ["cdkFocusChange"], exportAs: ["cdkMonitorFocus"] }, { kind: "component", type: OwlMultiYearViewComponent, selector: "owl-date-time-multi-year-view", inputs: ["selectMode", "selected", "selecteds", "pickerDateTime", "dateFilter", "minDate", "maxDate"], outputs: ["change", "yearSelected", "pickerDateTimeChange", "keyboardEnter"] }, { kind: "component", type: OwlYearViewComponent, selector: "owl-date-time-year-view", inputs: ["selectMode", "selected", "selecteds", "pickerDateTime", "dateFilter", "minDate", "maxDate"], outputs: ["change", "monthSelected", "pickerDateTimeChange", "keyboardEnter"], exportAs: ["owlMonthView"] }, { kind: "component", type: OwlMonthViewComponent, selector: "owl-date-time-month-view", inputs: ["hideOtherMonths", "showCalendarWeeks", "firstDayOfWeek", "selectMode", "selected", "selecteds", "pickerDateTime", "dateFilter", "minDate", "maxDate"], outputs: ["selectedChange", "userSelection", "pickerDateTimeChange"], exportAs: ["owlYearView"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2132
2167
|
}
|
|
2133
2168
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlCalendarComponent, decorators: [{
|
|
2134
2169
|
type: Component,
|
|
2135
2170
|
args: [{ selector: 'owl-date-time-calendar', exportAs: 'owlDateTimeCalendar', standalone: false, host: {
|
|
2136
2171
|
'[class.owl-dt-calendar]': 'owlDTCalendarClass'
|
|
2137
|
-
}, preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"owl-dt-calendar-control\">\r\n <!--
|
|
2172
|
+
}, preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"owl-dt-calendar-control\">\r\n <!-- \u0424\u043E\u043A\u0443\u0441 \u043F\u0440\u0438 \u043D\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043A\u043B\u0430\u0432\u0438\u0448\u0435\u0439 Tab (http://kizu.ru/en/blog/keyboard-only-focus/#x) -->\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [style.visibility]=\"showControlArrows ? 'visible' : 'hidden'\"\r\n [disabled]=\"!prevButtonEnabled()\"\r\n [attr.aria-label]=\"prevButtonLabel\"\r\n (click)=\"previousClicked()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043B\u0435\u0432\u043E\"> -->\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 250.738 250.738\"\r\n style=\"enable-background: new 0 0 250.738 250.738\"\r\n xml:space=\"preserve\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n >\r\n <path\r\n style=\"fill-rule: evenodd; clip-rule: evenodd\"\r\n d=\"M96.633,125.369l95.053-94.533c7.101-7.055,7.101-18.492,0-25.546 c-7.1-7.054-18.613-7.054-25.714,0L58.989,111.689c-3.784,3.759-5.487,8.759-5.238,13.68c-0.249,4.922,1.454,9.921,5.238,13.681 l106.983,106.398c7.101,7.055,18.613,7.055,25.714,0c7.101-7.054,7.101-18.491,0-25.544L96.633,125.369z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </button>\r\n <div class=\"owl-dt-calendar-control-content\">\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-period-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [attr.aria-label]=\"periodButtonLabel\"\r\n (click)=\"toggleViews()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n {{ periodButtonText }}\r\n\r\n <span\r\n class=\"owl-dt-control-button-arrow\"\r\n [style.transform]=\"\r\n 'rotate(' + (isMonthView ? 0 : 180) + 'deg)'\r\n \"\r\n >\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430\"> -->\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n width=\"50%\"\r\n height=\"50%\"\r\n viewBox=\"0 0 292.362 292.362\"\r\n style=\"enable-background: new 0 0 292.362 292.362\"\r\n xml:space=\"preserve\"\r\n >\r\n <g>\r\n <path\r\n d=\"M286.935,69.377c-3.614-3.617-7.898-5.424-12.848-5.424H18.274c-4.952,0-9.233,1.807-12.85,5.424\r\n C1.807,72.998,0,77.279,0,82.228c0,4.948,1.807,9.229,5.424,12.847l127.907,127.907c3.621,3.617,7.902,5.428,12.85,5.428\r\n s9.233-1.811,12.847-5.428L286.935,95.074c3.613-3.617,5.427-7.898,5.427-12.847C292.362,77.279,290.548,72.998,286.935,69.377z\"\r\n />\r\n </g>\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </span>\r\n </button>\r\n </div>\r\n <button\r\n class=\"owl-dt-control owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"0\"\r\n [style.visibility]=\"showControlArrows ? 'visible' : 'hidden'\"\r\n [disabled]=\"!nextButtonEnabled()\"\r\n [attr.aria-label]=\"nextButtonLabel\"\r\n (click)=\"nextClicked()\"\r\n >\r\n <span\r\n class=\"owl-dt-control-content owl-dt-control-button-content\"\r\n tabindex=\"-1\"\r\n >\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043F\u0440\u0430\u0432\u043E\"> -->\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 250.738 250.738\"\r\n style=\"enable-background: new 0 0 250.738 250.738\"\r\n xml:space=\"preserve\"\r\n >\r\n <path\r\n style=\"fill-rule: evenodd; clip-rule: evenodd\"\r\n d=\"M191.75,111.689L84.766,5.291c-7.1-7.055-18.613-7.055-25.713,0\r\n c-7.101,7.054-7.101,18.49,0,25.544l95.053,94.534l-95.053,94.533c-7.101,7.054-7.101,18.491,0,25.545\r\n c7.1,7.054,18.613,7.054,25.713,0L191.75,139.05c3.784-3.759,5.487-8.759,5.238-13.681\r\n C197.237,120.447,195.534,115.448,191.75,111.689z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n </button>\r\n</div>\r\n<div class=\"owl-dt-calendar-main\" cdkMonitorSubtreeFocus tabindex=\"-1\">\r\n @switch (currentView) {\r\n @case (DateView.MONTH) {\r\n <owl-date-time-month-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [firstDayOfWeek]=\"firstDayOfWeek\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [showCalendarWeeks]=\"showCalendarWeeks\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n [hideOtherMonths]=\"hideOtherMonths\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (selectedChange)=\"dateSelected($event)\"\r\n (userSelection)=\"userSelected()\"\r\n ></owl-date-time-month-view>\r\n }\r\n @case (DateView.YEAR) {\r\n <owl-date-time-year-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n (keyboardEnter)=\"focusActiveCell()\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (monthSelected)=\"selectMonthInYearView($event)\"\r\n (change)=\"goToDateInView($event, DateView.MONTH)\"\r\n ></owl-date-time-year-view>\r\n }\r\n @case (DateView.MULTI_YEARS) {\r\n <owl-date-time-multi-year-view\r\n [pickerDateTime]=\"pickerDateTime\"\r\n [selected]=\"selected\"\r\n [selecteds]=\"selecteds\"\r\n [selectMode]=\"selectMode\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [dateFilter]=\"dateFilter\"\r\n (keyboardEnter)=\"focusActiveCell()\"\r\n (pickerDateTimeChange)=\"handlePickerDateTimeChange($event)\"\r\n (yearSelected)=\"selectYearInMultiYearView($event)\"\r\n (change)=\"goToDateInView($event, DateView.YEAR)\"\r\n ></owl-date-time-multi-year-view>\r\n }\r\n }\r\n</div>\r\n" }]
|
|
2138
2173
|
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: OwlDateTimeIntl }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: DateTimeAdapter, decorators: [{
|
|
2139
2174
|
type: Optional
|
|
2140
2175
|
}] }, { type: undefined, decorators: [{
|
|
@@ -2187,12 +2222,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
2187
2222
|
*/
|
|
2188
2223
|
class OwlTimerBoxComponent {
|
|
2189
2224
|
get displayValue() {
|
|
2190
|
-
if (this.
|
|
2191
|
-
//
|
|
2225
|
+
if (this.isEditing) {
|
|
2226
|
+
// Не переформатируем значение, пока пользователь его редактирует
|
|
2192
2227
|
return this.valueInput.nativeElement.value;
|
|
2193
2228
|
}
|
|
2194
|
-
const value = this.boxValue
|
|
2195
|
-
if (value
|
|
2229
|
+
const value = this.boxValue ?? this.value;
|
|
2230
|
+
if (value == null || isNaN(value)) {
|
|
2196
2231
|
return '';
|
|
2197
2232
|
}
|
|
2198
2233
|
return value < 10 ? '0' + value.toString() : value.toString();
|
|
@@ -2200,14 +2235,15 @@ class OwlTimerBoxComponent {
|
|
|
2200
2235
|
get owlDTTimerBoxClass() {
|
|
2201
2236
|
return true;
|
|
2202
2237
|
}
|
|
2203
|
-
constructor() {
|
|
2238
|
+
constructor(changeDetector) {
|
|
2239
|
+
this.changeDetector = changeDetector;
|
|
2204
2240
|
this.showDivider = false;
|
|
2205
2241
|
this.step = 1;
|
|
2206
2242
|
this.valueChange = new EventEmitter();
|
|
2207
2243
|
this.inputChange = new EventEmitter();
|
|
2208
2244
|
this.inputStream = new Subject();
|
|
2209
2245
|
this.inputStreamSub = Subscription.EMPTY;
|
|
2210
|
-
this.
|
|
2246
|
+
this.isEditing = false;
|
|
2211
2247
|
this.onValueInputMouseWheelBind = this.onValueInputMouseWheel.bind(this);
|
|
2212
2248
|
}
|
|
2213
2249
|
ngOnInit() {
|
|
@@ -2230,19 +2266,26 @@ class OwlTimerBoxComponent {
|
|
|
2230
2266
|
this.updateValue(this.value - this.step);
|
|
2231
2267
|
}
|
|
2232
2268
|
handleInputChange(val) {
|
|
2269
|
+
this.isEditing = true;
|
|
2233
2270
|
this.inputStream.next(val);
|
|
2234
2271
|
}
|
|
2235
2272
|
focusIn() {
|
|
2236
|
-
this.
|
|
2273
|
+
this.isEditing = true;
|
|
2237
2274
|
}
|
|
2238
2275
|
focusOut(value) {
|
|
2239
|
-
|
|
2240
|
-
|
|
2276
|
+
const wasEditing = this.isEditing;
|
|
2277
|
+
this.isEditing = false;
|
|
2278
|
+
// Отменяем ожидающий debounce: blur сразу фиксирует текущий текст
|
|
2279
|
+
this.inputStream.next('');
|
|
2280
|
+
if (wasEditing && value) {
|
|
2241
2281
|
const inputValue = coerceNumberProperty(value, 0);
|
|
2242
2282
|
this.updateValueViaInput(inputValue);
|
|
2243
2283
|
}
|
|
2244
2284
|
}
|
|
2245
2285
|
updateValue(value) {
|
|
2286
|
+
// Шаг заменяет введённый текст; отложенный input и blur не должны откатывать значение
|
|
2287
|
+
this.isEditing = false;
|
|
2288
|
+
this.inputStream.next('');
|
|
2246
2289
|
this.valueChange.emit(value);
|
|
2247
2290
|
}
|
|
2248
2291
|
updateValueViaInput(value) {
|
|
@@ -2253,7 +2296,7 @@ class OwlTimerBoxComponent {
|
|
|
2253
2296
|
}
|
|
2254
2297
|
onValueInputMouseWheel(event) {
|
|
2255
2298
|
event = event || window.event;
|
|
2256
|
-
const delta = event.
|
|
2299
|
+
const delta = event.deltaY != null ? -event.deltaY : event.wheelDelta || -event.detail;
|
|
2257
2300
|
if (delta > 0) {
|
|
2258
2301
|
if (!this.upBtnDisabled) {
|
|
2259
2302
|
this.upBtnClicked();
|
|
@@ -2264,23 +2307,24 @@ class OwlTimerBoxComponent {
|
|
|
2264
2307
|
this.downBtnClicked();
|
|
2265
2308
|
}
|
|
2266
2309
|
}
|
|
2310
|
+
this.changeDetector.markForCheck();
|
|
2267
2311
|
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
|
|
2268
2312
|
}
|
|
2269
2313
|
bindValueInputMouseWheel() {
|
|
2270
|
-
this.valueInput.nativeElement.addEventListener('onwheel' in
|
|
2314
|
+
this.valueInput.nativeElement.addEventListener('onwheel' in this.valueInput.nativeElement.ownerDocument ? 'wheel' : 'mousewheel', this.onValueInputMouseWheelBind);
|
|
2271
2315
|
}
|
|
2272
2316
|
unbindValueInputMouseWheel() {
|
|
2273
|
-
this.valueInput.nativeElement.removeEventListener('onwheel' in
|
|
2317
|
+
this.valueInput.nativeElement.removeEventListener('onwheel' in this.valueInput.nativeElement.ownerDocument ? 'wheel' : 'mousewheel', this.onValueInputMouseWheelBind);
|
|
2274
2318
|
}
|
|
2275
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlTimerBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2276
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: OwlTimerBoxComponent, isStandalone: false, selector: "owl-date-time-timer-box", inputs: { showDivider: "showDivider", upBtnAriaLabel: "upBtnAriaLabel", upBtnDisabled: "upBtnDisabled", downBtnAriaLabel: "downBtnAriaLabel", downBtnDisabled: "downBtnDisabled", boxValue: "boxValue", value: "value", min: "min", max: "max", step: "step", inputLabel: "inputLabel" }, outputs: { valueChange: "valueChange", inputChange: "inputChange" }, host: { properties: { "class.owl-dt-timer-box": "owlDTTimerBoxClass" } }, viewQueries: [{ propertyName: "valueInput", first: true, predicate: ["valueInput"], descendants: true, static: true }], exportAs: ["owlDateTimeTimerBox"], ngImport: i0, template: "@if (showDivider) {\r\n <div class=\"owl-dt-timer-divider\" aria-hidden=\"true\"></div>\r\n}\r\n<button\r\n class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n [disabled]=\"upBtnDisabled\"\r\n [attr.aria-label]=\"upBtnAriaLabel\"\r\n (click)=\"upBtnClicked()\"\r\n>\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG
|
|
2319
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlTimerBoxComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2320
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: OwlTimerBoxComponent, isStandalone: false, selector: "owl-date-time-timer-box", inputs: { showDivider: "showDivider", upBtnAriaLabel: "upBtnAriaLabel", upBtnDisabled: "upBtnDisabled", downBtnAriaLabel: "downBtnAriaLabel", downBtnDisabled: "downBtnDisabled", boxValue: "boxValue", value: "value", min: "min", max: "max", step: "step", inputLabel: "inputLabel" }, outputs: { valueChange: "valueChange", inputChange: "inputChange" }, host: { properties: { "class.owl-dt-timer-box": "owlDTTimerBoxClass" } }, viewQueries: [{ propertyName: "valueInput", first: true, predicate: ["valueInput"], descendants: true, static: true }], exportAs: ["owlDateTimeTimerBox"], ngImport: i0, template: "@if (showDivider) {\r\n <div class=\"owl-dt-timer-divider\" aria-hidden=\"true\"></div>\r\n}\r\n<button\r\n class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n [disabled]=\"upBtnDisabled\"\r\n [attr.aria-label]=\"upBtnAriaLabel\"\r\n (click)=\"upBtnClicked()\"\r\n>\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u0432\u0435\u0440\u0445\"> -->\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 451.847 451.846\"\r\n style=\"enable-background: new 0 0 451.847 451.846\"\r\n xml:space=\"preserve\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n >\r\n <path\r\n d=\"M248.292,106.406l194.281,194.29c12.365,12.359,12.365,32.391,0,44.744c-12.354,12.354-32.391,12.354-44.744,0\r\n L225.923,173.529L54.018,345.44c-12.36,12.354-32.395,12.354-44.748,0c-12.359-12.354-12.359-32.391,0-44.75L203.554,106.4\r\n c6.18-6.174,14.271-9.259,22.369-9.259C234.018,97.141,242.115,100.232,248.292,106.406z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n</button>\r\n<label class=\"owl-dt-timer-content\">\r\n <input\r\n class=\"owl-dt-timer-input\"\r\n maxlength=\"2\"\r\n [value]=\"displayValue\"\r\n (keydown.arrowup)=\"!upBtnDisabled && upBtnClicked()\"\r\n (keydown.arrowdown)=\"!downBtnDisabled && downBtnClicked()\"\r\n (input)=\"handleInputChange(valueInput.value)\"\r\n (focusin)=\"focusIn()\"\r\n (focusout)=\"focusOut(valueInput.value)\"\r\n #valueInput\r\n />\r\n <span class=\"owl-hidden-accessible\">{{ inputLabel }}</span>\r\n</label>\r\n<button\r\n class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n [disabled]=\"downBtnDisabled\"\r\n [attr.aria-label]=\"downBtnAriaLabel\"\r\n (click)=\"downBtnClicked()\"\r\n>\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043D\u0438\u0437\"> -->\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 451.847 451.846\"\r\n style=\"enable-background: new 0 0 451.847 451.846\"\r\n xml:space=\"preserve\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n >\r\n <path\r\n d=\"M225.923,354.706c-8.098,0-16.195-3.092-22.369-9.263L9.27,151.157c-12.359-12.359-12.359-32.397,0-44.751\r\n c12.354-12.354,32.388-12.354,44.748,0l171.905,171.915l171.906-171.909c12.359-12.354,32.391-12.354,44.744,0\r\n c12.365,12.354,12.365,32.392,0,44.751L248.292,345.449C242.115,351.621,234.018,354.706,225.923,354.706z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n</button>\r\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2277
2321
|
}
|
|
2278
2322
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlTimerBoxComponent, decorators: [{
|
|
2279
2323
|
type: Component,
|
|
2280
2324
|
args: [{ exportAs: 'owlDateTimeTimerBox', selector: 'owl-date-time-timer-box', standalone: false, preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2281
2325
|
'[class.owl-dt-timer-box]': 'owlDTTimerBoxClass'
|
|
2282
|
-
}, template: "@if (showDivider) {\r\n <div class=\"owl-dt-timer-divider\" aria-hidden=\"true\"></div>\r\n}\r\n<button\r\n class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n [disabled]=\"upBtnDisabled\"\r\n [attr.aria-label]=\"upBtnAriaLabel\"\r\n (click)=\"upBtnClicked()\"\r\n>\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG
|
|
2283
|
-
}], ctorParameters: () => [], propDecorators: { showDivider: [{
|
|
2326
|
+
}, template: "@if (showDivider) {\r\n <div class=\"owl-dt-timer-divider\" aria-hidden=\"true\"></div>\r\n}\r\n<button\r\n class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n [disabled]=\"upBtnDisabled\"\r\n [attr.aria-label]=\"upBtnAriaLabel\"\r\n (click)=\"upBtnClicked()\"\r\n>\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u0432\u0435\u0440\u0445\"> -->\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 451.847 451.846\"\r\n style=\"enable-background: new 0 0 451.847 451.846\"\r\n xml:space=\"preserve\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n >\r\n <path\r\n d=\"M248.292,106.406l194.281,194.29c12.365,12.359,12.365,32.391,0,44.744c-12.354,12.354-32.391,12.354-44.744,0\r\n L225.923,173.529L54.018,345.44c-12.36,12.354-32.395,12.354-44.748,0c-12.359-12.354-12.359-32.391,0-44.75L203.554,106.4\r\n c6.18-6.174,14.271-9.259,22.369-9.259C234.018,97.141,242.115,100.232,248.292,106.406z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n</button>\r\n<label class=\"owl-dt-timer-content\">\r\n <input\r\n class=\"owl-dt-timer-input\"\r\n maxlength=\"2\"\r\n [value]=\"displayValue\"\r\n (keydown.arrowup)=\"!upBtnDisabled && upBtnClicked()\"\r\n (keydown.arrowdown)=\"!downBtnDisabled && downBtnClicked()\"\r\n (input)=\"handleInputChange(valueInput.value)\"\r\n (focusin)=\"focusIn()\"\r\n (focusout)=\"focusOut(valueInput.value)\"\r\n #valueInput\r\n />\r\n <span class=\"owl-hidden-accessible\">{{ inputLabel }}</span>\r\n</label>\r\n<button\r\n class=\"owl-dt-control-button owl-dt-control-arrow-button\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n [disabled]=\"downBtnDisabled\"\r\n [attr.aria-label]=\"downBtnAriaLabel\"\r\n (click)=\"downBtnClicked()\"\r\n>\r\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\r\n <!-- <editor-fold desc=\"SVG-\u0441\u0442\u0440\u0435\u043B\u043A\u0430 \u0432\u043D\u0438\u0437\"> -->\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n version=\"1.1\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 451.847 451.846\"\r\n style=\"enable-background: new 0 0 451.847 451.846\"\r\n xml:space=\"preserve\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n >\r\n <path\r\n d=\"M225.923,354.706c-8.098,0-16.195-3.092-22.369-9.263L9.27,151.157c-12.359-12.359-12.359-32.397,0-44.751\r\n c12.354-12.354,32.388-12.354,44.748,0l171.905,171.915l171.906-171.909c12.359-12.354,32.391-12.354,44.744,0\r\n c12.365,12.354,12.365,32.392,0,44.751L248.292,345.449C242.115,351.621,234.018,354.706,225.923,354.706z\"\r\n />\r\n </svg>\r\n <!-- </editor-fold> -->\r\n </span>\r\n</button>\r\n" }]
|
|
2327
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { showDivider: [{
|
|
2284
2328
|
type: Input
|
|
2285
2329
|
}], upBtnAriaLabel: [{
|
|
2286
2330
|
type: Input
|
|
@@ -2321,7 +2365,7 @@ class OwlTimerComponent {
|
|
|
2321
2365
|
set pickerDateTime(value) {
|
|
2322
2366
|
value = this.dateTimeAdapter.deserialize(value);
|
|
2323
2367
|
this._pickerDateTime =
|
|
2324
|
-
this.getValidDate(value)
|
|
2368
|
+
this.getValidDate(value) ?? this.dateTimeAdapter.now();
|
|
2325
2369
|
}
|
|
2326
2370
|
get minDateTime() {
|
|
2327
2371
|
return this._minDateTime;
|
|
@@ -2341,9 +2385,9 @@ class OwlTimerComponent {
|
|
|
2341
2385
|
return this.dateTimeAdapter.getHours(this.pickerDateTime);
|
|
2342
2386
|
}
|
|
2343
2387
|
/**
|
|
2344
|
-
*
|
|
2345
|
-
*
|
|
2346
|
-
*
|
|
2388
|
+
* Значение, отображаемое в hourBox
|
|
2389
|
+
* Оно требуется, поскольку значение в hourBox отличается
|
|
2390
|
+
* от hourValue в режиме hour12Timer
|
|
2347
2391
|
* */
|
|
2348
2392
|
get hourBoxValue() {
|
|
2349
2393
|
let hours = this.hourValue;
|
|
@@ -2409,38 +2453,47 @@ class OwlTimerComponent {
|
|
|
2409
2453
|
this.pickerIntl = pickerIntl;
|
|
2410
2454
|
this.cdRef = cdRef;
|
|
2411
2455
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
2412
|
-
this.
|
|
2456
|
+
this.injector = inject(Injector);
|
|
2457
|
+
this.destroyRef = inject(DestroyRef);
|
|
2458
|
+
this.intlChangesSub = Subscription.EMPTY;
|
|
2459
|
+
this.isPM = false; // Относится ли текущее время к PM в 12-часовом формате
|
|
2413
2460
|
/**
|
|
2414
|
-
*
|
|
2461
|
+
* Количество часов за один шаг
|
|
2415
2462
|
*/
|
|
2416
2463
|
this.stepHour = 1;
|
|
2417
2464
|
/**
|
|
2418
|
-
*
|
|
2465
|
+
* Количество минут за один шаг
|
|
2419
2466
|
*/
|
|
2420
2467
|
this.stepMinute = 1;
|
|
2421
2468
|
/**
|
|
2422
|
-
*
|
|
2469
|
+
* Количество секунд за один шаг
|
|
2423
2470
|
*/
|
|
2424
2471
|
this.stepSecond = 1;
|
|
2425
2472
|
this.selectedChange = new EventEmitter();
|
|
2473
|
+
this.intlChangesSub = this.pickerIntl.changes.subscribe(() => this.cdRef.markForCheck());
|
|
2426
2474
|
}
|
|
2427
2475
|
ngOnInit() { }
|
|
2476
|
+
ngOnDestroy() {
|
|
2477
|
+
this.intlChangesSub.unsubscribe();
|
|
2478
|
+
}
|
|
2428
2479
|
/**
|
|
2429
|
-
*
|
|
2480
|
+
* Переводит фокус на элемент компонента
|
|
2430
2481
|
* */
|
|
2431
2482
|
focus() {
|
|
2432
|
-
this.
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2483
|
+
if (this.destroyRef.destroyed) {
|
|
2484
|
+
return;
|
|
2485
|
+
}
|
|
2486
|
+
this.focusRef?.destroy();
|
|
2487
|
+
this.focusRef = afterNextRender({
|
|
2488
|
+
write: () => {
|
|
2489
|
+
this.focusRef = undefined;
|
|
2437
2490
|
this.elmRef.nativeElement.focus();
|
|
2438
|
-
}
|
|
2439
|
-
});
|
|
2491
|
+
}
|
|
2492
|
+
}, { injector: this.injector });
|
|
2440
2493
|
}
|
|
2441
2494
|
/**
|
|
2442
|
-
*
|
|
2443
|
-
*
|
|
2495
|
+
* Задаёт час при вводе текста в поле времени
|
|
2496
|
+
* Нужно для обработки часа в 12-часовом формате времени
|
|
2444
2497
|
* */
|
|
2445
2498
|
setHourValueViaInput(hours) {
|
|
2446
2499
|
if (this.hour12Timer && this.isPM && hours >= 1 && hours <= 11) {
|
|
@@ -2482,52 +2535,52 @@ class OwlTimerComponent {
|
|
|
2482
2535
|
event.preventDefault();
|
|
2483
2536
|
}
|
|
2484
2537
|
/**
|
|
2485
|
-
*
|
|
2538
|
+
* Проверяет доступность кнопки увеличения часов
|
|
2486
2539
|
*/
|
|
2487
2540
|
upHourEnabled() {
|
|
2488
|
-
return (
|
|
2541
|
+
return (this.maxDateTime == null ||
|
|
2489
2542
|
this.compareHours(this.stepHour, this.maxDateTime) < 1);
|
|
2490
2543
|
}
|
|
2491
2544
|
/**
|
|
2492
|
-
*
|
|
2545
|
+
* Проверяет доступность кнопки уменьшения часов
|
|
2493
2546
|
*/
|
|
2494
2547
|
downHourEnabled() {
|
|
2495
|
-
return (
|
|
2548
|
+
return (this.minDateTime == null ||
|
|
2496
2549
|
this.compareHours(-this.stepHour, this.minDateTime) > -1);
|
|
2497
2550
|
}
|
|
2498
2551
|
/**
|
|
2499
|
-
*
|
|
2552
|
+
* Проверяет доступность кнопки увеличения минут
|
|
2500
2553
|
*/
|
|
2501
2554
|
upMinuteEnabled() {
|
|
2502
|
-
return (
|
|
2555
|
+
return (this.maxDateTime == null ||
|
|
2503
2556
|
this.compareMinutes(this.stepMinute, this.maxDateTime) < 1);
|
|
2504
2557
|
}
|
|
2505
2558
|
/**
|
|
2506
|
-
*
|
|
2559
|
+
* Проверяет доступность кнопки уменьшения минут
|
|
2507
2560
|
*/
|
|
2508
2561
|
downMinuteEnabled() {
|
|
2509
|
-
return (
|
|
2562
|
+
return (this.minDateTime == null ||
|
|
2510
2563
|
this.compareMinutes(-this.stepMinute, this.minDateTime) > -1);
|
|
2511
2564
|
}
|
|
2512
2565
|
/**
|
|
2513
|
-
*
|
|
2566
|
+
* Проверяет доступность кнопки увеличения секунд
|
|
2514
2567
|
*/
|
|
2515
2568
|
upSecondEnabled() {
|
|
2516
|
-
return (
|
|
2569
|
+
return (this.maxDateTime == null ||
|
|
2517
2570
|
this.compareSeconds(this.stepSecond, this.maxDateTime) < 1);
|
|
2518
2571
|
}
|
|
2519
2572
|
/**
|
|
2520
|
-
*
|
|
2573
|
+
* Проверяет доступность кнопки уменьшения секунд
|
|
2521
2574
|
*/
|
|
2522
2575
|
downSecondEnabled() {
|
|
2523
|
-
return (
|
|
2576
|
+
return (this.minDateTime == null ||
|
|
2524
2577
|
this.compareSeconds(-this.stepSecond, this.minDateTime) > -1);
|
|
2525
2578
|
}
|
|
2526
2579
|
/**
|
|
2527
|
-
*
|
|
2528
|
-
* 1
|
|
2529
|
-
* -1
|
|
2530
|
-
* 0
|
|
2580
|
+
* Изменяет отображаемый час и сравнивает результат с указанной датой
|
|
2581
|
+
* 1 — позже comparedDate
|
|
2582
|
+
* -1 — раньше comparedDate
|
|
2583
|
+
* 0 — совпадает с comparedDate
|
|
2531
2584
|
* */
|
|
2532
2585
|
compareHours(amount, comparedDate) {
|
|
2533
2586
|
const hours = this.dateTimeAdapter.getHours(this.pickerDateTime) + amount;
|
|
@@ -2535,10 +2588,10 @@ class OwlTimerComponent {
|
|
|
2535
2588
|
return this.dateTimeAdapter.compare(result, comparedDate);
|
|
2536
2589
|
}
|
|
2537
2590
|
/**
|
|
2538
|
-
*
|
|
2539
|
-
* 1
|
|
2540
|
-
* -1
|
|
2541
|
-
* 0
|
|
2591
|
+
* Изменяет отображаемую минуту и сравнивает результат с указанной датой
|
|
2592
|
+
* 1 — позже comparedDate
|
|
2593
|
+
* -1 — раньше comparedDate
|
|
2594
|
+
* 0 — совпадает с comparedDate
|
|
2542
2595
|
* */
|
|
2543
2596
|
compareMinutes(amount, comparedDate) {
|
|
2544
2597
|
const minutes = this.dateTimeAdapter.getMinutes(this.pickerDateTime) + amount;
|
|
@@ -2546,10 +2599,10 @@ class OwlTimerComponent {
|
|
|
2546
2599
|
return this.dateTimeAdapter.compare(result, comparedDate);
|
|
2547
2600
|
}
|
|
2548
2601
|
/**
|
|
2549
|
-
*
|
|
2550
|
-
* 1
|
|
2551
|
-
* -1
|
|
2552
|
-
* 0
|
|
2602
|
+
* Изменяет отображаемую секунду и сравнивает результат с указанной датой
|
|
2603
|
+
* 1 — позже comparedDate
|
|
2604
|
+
* -1 — раньше comparedDate
|
|
2605
|
+
* 0 — совпадает с comparedDate
|
|
2553
2606
|
* */
|
|
2554
2607
|
compareSeconds(amount, comparedDate) {
|
|
2555
2608
|
const seconds = this.dateTimeAdapter.getSeconds(this.pickerDateTime) + amount;
|
|
@@ -2557,7 +2610,7 @@ class OwlTimerComponent {
|
|
|
2557
2610
|
return this.dateTimeAdapter.compare(result, comparedDate);
|
|
2558
2611
|
}
|
|
2559
2612
|
/**
|
|
2560
|
-
*
|
|
2613
|
+
* Возвращает корректный объект даты
|
|
2561
2614
|
*/
|
|
2562
2615
|
getValidDate(obj) {
|
|
2563
2616
|
return this.dateTimeAdapter.isDateInstance(obj) &&
|
|
@@ -2616,7 +2669,7 @@ class OwlDateTimeContainerComponent {
|
|
|
2616
2669
|
return this._clampedPickerDateTime;
|
|
2617
2670
|
}
|
|
2618
2671
|
set pickerDateTime(value) {
|
|
2619
|
-
if (value) {
|
|
2672
|
+
if (value != null) {
|
|
2620
2673
|
this._clampedPickerDateTime = this.dateTimeAdapter.clampDate(value, this.picker.minDateTime, this.picker.maxDateTime);
|
|
2621
2674
|
}
|
|
2622
2675
|
this.cdRef.markForCheck();
|
|
@@ -2631,39 +2684,39 @@ class OwlDateTimeContainerComponent {
|
|
|
2631
2684
|
return this.pickerIntl.setBtnLabel;
|
|
2632
2685
|
}
|
|
2633
2686
|
/**
|
|
2634
|
-
*
|
|
2687
|
+
* Подпись начала диапазона ('from')
|
|
2635
2688
|
* */
|
|
2636
2689
|
get fromLabel() {
|
|
2637
2690
|
return this.pickerIntl.rangeFromLabel;
|
|
2638
2691
|
}
|
|
2639
2692
|
/**
|
|
2640
|
-
*
|
|
2693
|
+
* Подпись конца диапазона ('to')
|
|
2641
2694
|
* */
|
|
2642
2695
|
get toLabel() {
|
|
2643
2696
|
return this.pickerIntl.rangeToLabel;
|
|
2644
2697
|
}
|
|
2645
2698
|
/**
|
|
2646
|
-
*
|
|
2699
|
+
* Отформатированное значение начала диапазона ('from')
|
|
2647
2700
|
* */
|
|
2648
2701
|
get fromFormattedValue() {
|
|
2649
2702
|
const value = this.picker.selecteds[0];
|
|
2650
|
-
return value
|
|
2703
|
+
return value != null
|
|
2651
2704
|
? this.dateTimeAdapter.format(value, this.picker.formatString)
|
|
2652
2705
|
: '';
|
|
2653
2706
|
}
|
|
2654
2707
|
/**
|
|
2655
|
-
*
|
|
2708
|
+
* Отформатированное значение конца диапазона ('to')
|
|
2656
2709
|
* */
|
|
2657
2710
|
get toFormattedValue() {
|
|
2658
2711
|
const value = this.picker.selecteds[1];
|
|
2659
|
-
return value
|
|
2712
|
+
return value != null
|
|
2660
2713
|
? this.dateTimeAdapter.format(value, this.picker.formatString)
|
|
2661
2714
|
: '';
|
|
2662
2715
|
}
|
|
2663
2716
|
/**
|
|
2664
|
-
*
|
|
2665
|
-
* 1)
|
|
2666
|
-
* 2)
|
|
2717
|
+
* Условия отображения кнопок управления:
|
|
2718
|
+
* 1) Режим компонента — 'dialog'
|
|
2719
|
+
* 2) Тип компонента отличается от 'calendar', а режим — от 'inline'
|
|
2667
2720
|
* */
|
|
2668
2721
|
get showControlButtons() {
|
|
2669
2722
|
return (this.picker.pickerMode === 'dialog' ||
|
|
@@ -2699,26 +2752,30 @@ class OwlDateTimeContainerComponent {
|
|
|
2699
2752
|
this.elmRef = elmRef;
|
|
2700
2753
|
this.pickerIntl = pickerIntl;
|
|
2701
2754
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
2702
|
-
this.activeSelectedIndex = 0; //
|
|
2703
|
-
/**
|
|
2755
|
+
this.activeSelectedIndex = 0; // Индекс активной границы диапазона (0: 'from', 1: 'to')
|
|
2756
|
+
/** Событие изменения состояния анимации */
|
|
2704
2757
|
this.animationStateChanged = new EventEmitter();
|
|
2705
2758
|
/**
|
|
2706
|
-
*
|
|
2759
|
+
* Поток запросов на закрытие компонента выбора
|
|
2707
2760
|
* */
|
|
2708
2761
|
this.hidePicker$ = new Subject();
|
|
2709
2762
|
/**
|
|
2710
|
-
*
|
|
2763
|
+
* Поток запросов на подтверждение выбранного значения
|
|
2711
2764
|
* */
|
|
2712
2765
|
this.confirmSelected$ = new Subject();
|
|
2713
2766
|
this.beforePickerOpened$ = new Subject();
|
|
2714
2767
|
this.pickerOpened$ = new Subject();
|
|
2768
|
+
this.pickerIntl.changes.pipe(takeUntilDestroyed()).subscribe(() => this.cdRef.markForCheck());
|
|
2769
|
+
}
|
|
2770
|
+
refreshView() {
|
|
2771
|
+
this.cdRef.markForCheck();
|
|
2715
2772
|
}
|
|
2716
2773
|
ngOnInit() {
|
|
2717
2774
|
if (this.picker.selectMode === 'range') {
|
|
2718
|
-
if (this.picker.selecteds[0]) {
|
|
2775
|
+
if (this.picker.selecteds[0] != null) {
|
|
2719
2776
|
this.retainStartTime = this.dateTimeAdapter.clone(this.picker.selecteds[0]);
|
|
2720
2777
|
}
|
|
2721
|
-
if (this.picker.selecteds[1]) {
|
|
2778
|
+
if (this.picker.selecteds[1] != null) {
|
|
2722
2779
|
this.retainEndTime = this.dateTimeAdapter.clone(this.picker.selecteds[1]);
|
|
2723
2780
|
}
|
|
2724
2781
|
}
|
|
@@ -2748,15 +2805,18 @@ class OwlDateTimeContainerComponent {
|
|
|
2748
2805
|
});
|
|
2749
2806
|
}
|
|
2750
2807
|
dateSelected(date) {
|
|
2808
|
+
if (this.picker.disabled) {
|
|
2809
|
+
return;
|
|
2810
|
+
}
|
|
2751
2811
|
let result;
|
|
2752
2812
|
if (this.picker.isInSingleMode) {
|
|
2753
2813
|
result = this.dateSelectedInSingleMode(date);
|
|
2754
|
-
if (result) {
|
|
2814
|
+
if (result != null) {
|
|
2755
2815
|
this.pickerDateTime = result;
|
|
2756
2816
|
this.picker.select(result);
|
|
2757
2817
|
}
|
|
2758
2818
|
else {
|
|
2759
|
-
//
|
|
2819
|
+
// Закрываем компонент выбора, если result равен null и pickerType равен 'calendar'
|
|
2760
2820
|
if (this.pickerType === 'calendar') {
|
|
2761
2821
|
this.hidePicker$.next(null);
|
|
2762
2822
|
}
|
|
@@ -2765,13 +2825,16 @@ class OwlDateTimeContainerComponent {
|
|
|
2765
2825
|
}
|
|
2766
2826
|
if (this.picker.isInRangeMode) {
|
|
2767
2827
|
result = this.dateSelectedInRangeMode(date);
|
|
2768
|
-
if (result) {
|
|
2828
|
+
if (result != null) {
|
|
2769
2829
|
this.pickerDateTime = result[this.activeSelectedIndex];
|
|
2770
2830
|
this.picker.select(result);
|
|
2771
2831
|
}
|
|
2772
2832
|
}
|
|
2773
2833
|
}
|
|
2774
2834
|
timeSelected(time) {
|
|
2835
|
+
if (this.picker.disabled) {
|
|
2836
|
+
return;
|
|
2837
|
+
}
|
|
2775
2838
|
this.pickerDateTime = this.dateTimeAdapter.clone(time);
|
|
2776
2839
|
if (!this.picker.dateTimeChecker(this.pickerDateTime)) {
|
|
2777
2840
|
return;
|
|
@@ -2782,13 +2845,13 @@ class OwlDateTimeContainerComponent {
|
|
|
2782
2845
|
}
|
|
2783
2846
|
if (this.picker.isInRangeMode) {
|
|
2784
2847
|
const selecteds = [...this.picker.selecteds];
|
|
2785
|
-
//
|
|
2786
|
-
//
|
|
2848
|
+
// Проверяем, находится ли начало диапазона после конца или конец перед началом
|
|
2849
|
+
// В этом случае задаём обеим границам диапазона одинаковое значение
|
|
2787
2850
|
if ((this.activeSelectedIndex === 0 &&
|
|
2788
|
-
selecteds[1] &&
|
|
2851
|
+
selecteds[1] != null &&
|
|
2789
2852
|
this.dateTimeAdapter.compare(this.pickerDateTime, selecteds[1]) === 1) ||
|
|
2790
2853
|
(this.activeSelectedIndex === 1 &&
|
|
2791
|
-
selecteds[0] &&
|
|
2854
|
+
selecteds[0] != null &&
|
|
2792
2855
|
this.dateTimeAdapter.compare(this.pickerDateTime, selecteds[0]) === -1)) {
|
|
2793
2856
|
selecteds[0] = this.pickerDateTime;
|
|
2794
2857
|
selecteds[1] = this.pickerDateTime;
|
|
@@ -2796,17 +2859,17 @@ class OwlDateTimeContainerComponent {
|
|
|
2796
2859
|
else {
|
|
2797
2860
|
selecteds[this.activeSelectedIndex] = this.pickerDateTime;
|
|
2798
2861
|
}
|
|
2799
|
-
if (selecteds[0]) {
|
|
2862
|
+
if (selecteds[0] != null) {
|
|
2800
2863
|
this.retainStartTime = this.dateTimeAdapter.clone(selecteds[0]);
|
|
2801
2864
|
}
|
|
2802
|
-
if (selecteds[1]) {
|
|
2865
|
+
if (selecteds[1] != null) {
|
|
2803
2866
|
this.retainEndTime = this.dateTimeAdapter.clone(selecteds[1]);
|
|
2804
2867
|
}
|
|
2805
2868
|
this.picker.select(selecteds);
|
|
2806
2869
|
}
|
|
2807
2870
|
}
|
|
2808
2871
|
/**
|
|
2809
|
-
*
|
|
2872
|
+
* Обрабатывает нажатие кнопки отмены
|
|
2810
2873
|
*/
|
|
2811
2874
|
onCancelClicked(event) {
|
|
2812
2875
|
this.hidePicker$.next(null);
|
|
@@ -2814,9 +2877,13 @@ class OwlDateTimeContainerComponent {
|
|
|
2814
2877
|
return;
|
|
2815
2878
|
}
|
|
2816
2879
|
/**
|
|
2817
|
-
*
|
|
2880
|
+
* Обрабатывает нажатие кнопки подтверждения
|
|
2818
2881
|
*/
|
|
2819
2882
|
onSetClicked(event) {
|
|
2883
|
+
if (this.picker.disabled) {
|
|
2884
|
+
event.preventDefault();
|
|
2885
|
+
return;
|
|
2886
|
+
}
|
|
2820
2887
|
if (!this.picker.dateTimeChecker(this.pickerDateTime)) {
|
|
2821
2888
|
this.hidePicker$.next(null);
|
|
2822
2889
|
event.preventDefault();
|
|
@@ -2827,7 +2894,7 @@ class OwlDateTimeContainerComponent {
|
|
|
2827
2894
|
return;
|
|
2828
2895
|
}
|
|
2829
2896
|
/**
|
|
2830
|
-
*
|
|
2897
|
+
* Обрабатывает выбор границы диапазона в группе переключателей
|
|
2831
2898
|
*/
|
|
2832
2899
|
handleClickOnInfoGroup(event, index) {
|
|
2833
2900
|
this.setActiveSelectedIndex(index);
|
|
@@ -2835,7 +2902,7 @@ class OwlDateTimeContainerComponent {
|
|
|
2835
2902
|
event.stopPropagation();
|
|
2836
2903
|
}
|
|
2837
2904
|
/**
|
|
2838
|
-
*
|
|
2905
|
+
* Обрабатывает выбор границы диапазона в группе переключателей
|
|
2839
2906
|
*/
|
|
2840
2907
|
handleKeydownOnInfoGroup(event, next, index) {
|
|
2841
2908
|
switch (event.keyCode) {
|
|
@@ -2873,10 +2940,11 @@ class OwlDateTimeContainerComponent {
|
|
|
2873
2940
|
easing: 'cubic-bezier(0.25, 0.8, 0.25, 1)',
|
|
2874
2941
|
fill: 'forwards'
|
|
2875
2942
|
});
|
|
2876
|
-
|
|
2943
|
+
const complete = () => {
|
|
2877
2944
|
this.handleContainerAnimationDone('enter');
|
|
2878
2945
|
event.animationComplete();
|
|
2879
|
-
}
|
|
2946
|
+
};
|
|
2947
|
+
animation.finished.then(complete, complete);
|
|
2880
2948
|
}
|
|
2881
2949
|
}
|
|
2882
2950
|
onAnimateLeave(event) {
|
|
@@ -2887,40 +2955,42 @@ class OwlDateTimeContainerComponent {
|
|
|
2887
2955
|
event.animationComplete();
|
|
2888
2956
|
}
|
|
2889
2957
|
else {
|
|
2890
|
-
event.target.animate([
|
|
2958
|
+
const animation = event.target.animate([
|
|
2891
2959
|
{ opacity: 1 },
|
|
2892
2960
|
{ opacity: 0 }
|
|
2893
2961
|
], {
|
|
2894
2962
|
duration: duration ?? 100,
|
|
2895
2963
|
easing: 'linear',
|
|
2896
2964
|
fill: 'forwards'
|
|
2897
|
-
})
|
|
2965
|
+
});
|
|
2966
|
+
const complete = () => {
|
|
2898
2967
|
this.handleContainerAnimationDone('leave');
|
|
2899
2968
|
event.animationComplete();
|
|
2900
|
-
}
|
|
2969
|
+
};
|
|
2970
|
+
animation.finished.then(complete, complete);
|
|
2901
2971
|
}
|
|
2902
2972
|
}
|
|
2903
2973
|
/**
|
|
2904
|
-
*
|
|
2974
|
+
* Задаёт значение activeSelectedIndex
|
|
2905
2975
|
*/
|
|
2906
2976
|
setActiveSelectedIndex(index) {
|
|
2907
2977
|
if (this.picker.selectMode === 'range' &&
|
|
2908
2978
|
this.activeSelectedIndex !== index) {
|
|
2909
2979
|
this.activeSelectedIndex = index;
|
|
2910
2980
|
const selected = this.picker.selecteds[this.activeSelectedIndex];
|
|
2911
|
-
if (this.picker.selecteds && selected) {
|
|
2981
|
+
if (this.picker.selecteds && selected != null) {
|
|
2912
2982
|
this.pickerDateTime = this.dateTimeAdapter.clone(selected);
|
|
2913
2983
|
}
|
|
2914
2984
|
}
|
|
2915
2985
|
return;
|
|
2916
2986
|
}
|
|
2917
2987
|
initPicker() {
|
|
2918
|
-
this.pickerDateTime = this.picker.startAt
|
|
2988
|
+
this.pickerDateTime = this.picker.startAt ?? this.dateTimeAdapter.now();
|
|
2919
2989
|
this.activeSelectedIndex = this.picker.selectMode === 'rangeTo' ? 1 : 0;
|
|
2920
2990
|
}
|
|
2921
2991
|
/**
|
|
2922
|
-
*
|
|
2923
|
-
*
|
|
2992
|
+
* Выбирает дату календаря в режиме single
|
|
2993
|
+
* Возвращает null, если дата не выбрана
|
|
2924
2994
|
*/
|
|
2925
2995
|
dateSelectedInSingleMode(date) {
|
|
2926
2996
|
if (this.dateTimeAdapter.isSameDay(date, this.picker.selected)) {
|
|
@@ -2929,28 +2999,28 @@ class OwlDateTimeContainerComponent {
|
|
|
2929
2999
|
return this.updateAndCheckCalendarDate(date);
|
|
2930
3000
|
}
|
|
2931
3001
|
/**
|
|
2932
|
-
*
|
|
3002
|
+
* Выбирает даты в режиме диапазона
|
|
2933
3003
|
*/
|
|
2934
3004
|
dateSelectedInRangeMode(date) {
|
|
2935
3005
|
let from = this.picker.selecteds[0];
|
|
2936
3006
|
let to = this.picker.selecteds[1];
|
|
2937
3007
|
const result = this.updateAndCheckCalendarDate(date);
|
|
2938
|
-
if (
|
|
3008
|
+
if (result == null) {
|
|
2939
3009
|
return null;
|
|
2940
3010
|
}
|
|
2941
|
-
//
|
|
2942
|
-
//
|
|
2943
|
-
//
|
|
3011
|
+
// Если указанный день совпадает с началом диапазона или находится после него,
|
|
3012
|
+
// задаём его как конец диапазона ('to')
|
|
3013
|
+
// Иначе задаём его как начало диапазона ('from'), а конец ('to') сбрасываем в null
|
|
2944
3014
|
if (this.picker.selectMode === 'range') {
|
|
2945
3015
|
if (this.picker.selecteds &&
|
|
2946
3016
|
this.picker.selecteds.length &&
|
|
2947
|
-
|
|
2948
|
-
from &&
|
|
3017
|
+
to == null &&
|
|
3018
|
+
from != null &&
|
|
2949
3019
|
this.dateTimeAdapter.differenceInCalendarDays(result, from) >= 0) {
|
|
2950
|
-
if (this.picker.endAt &&
|
|
3020
|
+
if (this.picker.endAt != null && this.retainEndTime == null) {
|
|
2951
3021
|
to = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(result), this.dateTimeAdapter.getMonth(result), this.dateTimeAdapter.getDate(result), this.dateTimeAdapter.getHours(this.picker.endAt), this.dateTimeAdapter.getMinutes(this.picker.endAt), this.dateTimeAdapter.getSeconds(this.picker.endAt));
|
|
2952
3022
|
}
|
|
2953
|
-
else if (this.retainEndTime) {
|
|
3023
|
+
else if (this.retainEndTime != null) {
|
|
2954
3024
|
to = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(result), this.dateTimeAdapter.getMonth(result), this.dateTimeAdapter.getDate(result), this.dateTimeAdapter.getHours(this.retainEndTime), this.dateTimeAdapter.getMinutes(this.retainEndTime), this.dateTimeAdapter.getSeconds(this.retainEndTime));
|
|
2955
3025
|
}
|
|
2956
3026
|
else {
|
|
@@ -2959,10 +3029,10 @@ class OwlDateTimeContainerComponent {
|
|
|
2959
3029
|
this.activeSelectedIndex = 1;
|
|
2960
3030
|
}
|
|
2961
3031
|
else {
|
|
2962
|
-
if (this.picker.startAt &&
|
|
3032
|
+
if (this.picker.startAt != null && this.retainStartTime == null) {
|
|
2963
3033
|
from = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(result), this.dateTimeAdapter.getMonth(result), this.dateTimeAdapter.getDate(result), this.dateTimeAdapter.getHours(this.picker.startAt), this.dateTimeAdapter.getMinutes(this.picker.startAt), this.dateTimeAdapter.getSeconds(this.picker.startAt));
|
|
2964
3034
|
}
|
|
2965
|
-
else if (this.retainStartTime) {
|
|
3035
|
+
else if (this.retainStartTime != null) {
|
|
2966
3036
|
from = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(result), this.dateTimeAdapter.getMonth(result), this.dateTimeAdapter.getDate(result), this.dateTimeAdapter.getHours(this.retainStartTime), this.dateTimeAdapter.getMinutes(this.retainStartTime), this.dateTimeAdapter.getSeconds(this.retainStartTime));
|
|
2967
3037
|
}
|
|
2968
3038
|
else {
|
|
@@ -2974,30 +3044,41 @@ class OwlDateTimeContainerComponent {
|
|
|
2974
3044
|
}
|
|
2975
3045
|
else if (this.picker.selectMode === 'rangeFrom') {
|
|
2976
3046
|
from = result;
|
|
2977
|
-
//
|
|
2978
|
-
if (to && this.dateTimeAdapter.compare(from, to) > 0) {
|
|
3047
|
+
// Если начало диапазона находится после конца, сбрасываем конец в null
|
|
3048
|
+
if (to != null && this.dateTimeAdapter.compare(from, to) > 0) {
|
|
2979
3049
|
to = null;
|
|
2980
3050
|
}
|
|
2981
3051
|
}
|
|
2982
3052
|
else if (this.picker.selectMode === 'rangeTo') {
|
|
2983
3053
|
to = result;
|
|
2984
|
-
//
|
|
2985
|
-
if (from && this.dateTimeAdapter.compare(from, to) > 0) {
|
|
3054
|
+
// Если начало диапазона находится после конца, сбрасываем начало в null
|
|
3055
|
+
if (from != null && this.dateTimeAdapter.compare(from, to) > 0) {
|
|
2986
3056
|
from = null;
|
|
2987
3057
|
}
|
|
2988
3058
|
}
|
|
3059
|
+
// Сохранённое время может выходить за min/max, даже если день доступен для выбора
|
|
3060
|
+
const selected = this.dateTimeAdapter.clampDate(this.activeSelectedIndex === 0 ? from : to, this.picker.minDateTime, this.picker.maxDateTime);
|
|
3061
|
+
if (!this.picker.dateTimeChecker(selected)) {
|
|
3062
|
+
return null;
|
|
3063
|
+
}
|
|
3064
|
+
if (this.activeSelectedIndex === 0) {
|
|
3065
|
+
from = selected;
|
|
3066
|
+
}
|
|
3067
|
+
else {
|
|
3068
|
+
to = selected;
|
|
3069
|
+
}
|
|
2989
3070
|
return [from, to];
|
|
2990
3071
|
}
|
|
2991
3072
|
/**
|
|
2992
|
-
*
|
|
2993
|
-
*
|
|
2994
|
-
*
|
|
2995
|
-
*
|
|
2996
|
-
*
|
|
3073
|
+
* Обновляет время указанной даты календаря и проверяет её допустимость
|
|
3074
|
+
* Поскольку время даты календаря по умолчанию равно 00:00:00, в режиме 'both'
|
|
3075
|
+
* перед выбором даты необходимо обновить её время
|
|
3076
|
+
* Если дата допустима, возвращает обновлённое значение dateTime
|
|
3077
|
+
* Если дата недопустима, возвращает null
|
|
2997
3078
|
*/
|
|
2998
3079
|
updateAndCheckCalendarDate(date) {
|
|
2999
3080
|
let result;
|
|
3000
|
-
//
|
|
3081
|
+
// В режиме 'both' обновляем время даты календаря
|
|
3001
3082
|
if (this.picker.pickerType === 'both') {
|
|
3002
3083
|
result = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(date), this.dateTimeAdapter.getMonth(date), this.dateTimeAdapter.getDate(date), this.dateTimeAdapter.getHours(this.pickerDateTime), this.dateTimeAdapter.getMinutes(this.pickerDateTime), this.dateTimeAdapter.getSeconds(this.pickerDateTime));
|
|
3003
3084
|
result = this.dateTimeAdapter.clampDate(result, this.picker.minDateTime, this.picker.maxDateTime);
|
|
@@ -3005,11 +3086,11 @@ class OwlDateTimeContainerComponent {
|
|
|
3005
3086
|
else {
|
|
3006
3087
|
result = this.dateTimeAdapter.clone(date);
|
|
3007
3088
|
}
|
|
3008
|
-
//
|
|
3089
|
+
// Проверяем обновлённое значение dateTime
|
|
3009
3090
|
return this.picker.dateTimeChecker(result) ? result : null;
|
|
3010
3091
|
}
|
|
3011
3092
|
/**
|
|
3012
|
-
*
|
|
3093
|
+
* Переводит фокус на компонент выбора
|
|
3013
3094
|
* */
|
|
3014
3095
|
focusPicker() {
|
|
3015
3096
|
if (this.picker.pickerMode === 'inline') {
|
|
@@ -3024,7 +3105,7 @@ class OwlDateTimeContainerComponent {
|
|
|
3024
3105
|
}
|
|
3025
3106
|
parseCssVariableDuration(el, cssVariableName) {
|
|
3026
3107
|
const durationStr = getComputedStyle(el).getPropertyValue(cssVariableName).trim();
|
|
3027
|
-
//
|
|
3108
|
+
// Переводим в миллисекунды
|
|
3028
3109
|
let duration = undefined;
|
|
3029
3110
|
if (durationStr.endsWith('ms')) {
|
|
3030
3111
|
duration = parseFloat(durationStr);
|
|
@@ -3069,51 +3150,51 @@ let uniqueId = 0;
|
|
|
3069
3150
|
class OwlDialogConfig {
|
|
3070
3151
|
constructor() {
|
|
3071
3152
|
/**
|
|
3072
|
-
* ID
|
|
3153
|
+
* ID элемента с описанием диалогового окна
|
|
3073
3154
|
*/
|
|
3074
3155
|
this.ariaDescribedBy = null;
|
|
3075
3156
|
/**
|
|
3076
|
-
*
|
|
3157
|
+
* Нужно ли переводить фокус на диалоговое окно при открытии
|
|
3077
3158
|
*/
|
|
3078
3159
|
this.autoFocus = true;
|
|
3079
|
-
/**
|
|
3160
|
+
/** Есть ли у диалогового окна фон */
|
|
3080
3161
|
this.hasBackdrop = true;
|
|
3081
|
-
/**
|
|
3162
|
+
/** Данные, передаваемые в дочерний компонент через DI */
|
|
3082
3163
|
this.data = null;
|
|
3083
|
-
/**
|
|
3164
|
+
/** Может ли пользователь закрыть диалоговое окно клавишей Escape или нажатием за его пределами */
|
|
3084
3165
|
this.disableClose = false;
|
|
3085
3166
|
/**
|
|
3086
|
-
*
|
|
3167
|
+
* ARIA-роль элемента диалогового окна
|
|
3087
3168
|
*/
|
|
3088
3169
|
this.role = 'dialog';
|
|
3089
3170
|
/**
|
|
3090
|
-
*
|
|
3171
|
+
* Пользовательский класс панели
|
|
3091
3172
|
* */
|
|
3092
3173
|
this.paneClass = '';
|
|
3093
3174
|
/**
|
|
3094
|
-
*
|
|
3175
|
+
* Событие мыши
|
|
3095
3176
|
* */
|
|
3096
3177
|
this.event = null;
|
|
3097
3178
|
/**
|
|
3098
|
-
*
|
|
3179
|
+
* Пользовательский класс фона
|
|
3099
3180
|
* */
|
|
3100
3181
|
this.backdropClass = '';
|
|
3101
3182
|
/**
|
|
3102
|
-
*
|
|
3183
|
+
* Нужно ли закрывать диалоговое окно при переходе назад или вперёд в истории браузера
|
|
3103
3184
|
* */
|
|
3104
3185
|
this.closeOnNavigation = true;
|
|
3105
|
-
/**
|
|
3186
|
+
/** Ширина диалогового окна */
|
|
3106
3187
|
this.width = '';
|
|
3107
|
-
/**
|
|
3188
|
+
/** Высота диалогового окна */
|
|
3108
3189
|
this.height = '';
|
|
3109
3190
|
/**
|
|
3110
|
-
*
|
|
3111
|
-
*
|
|
3191
|
+
* Максимальная ширина overlay-панели
|
|
3192
|
+
* Числовое значение задаётся в пикселях
|
|
3112
3193
|
* */
|
|
3113
3194
|
this.maxWidth = '85vw';
|
|
3114
3195
|
/**
|
|
3115
|
-
*
|
|
3116
|
-
*
|
|
3196
|
+
* Стратегия прокрутки при открытом диалоговом окне
|
|
3197
|
+
* Подробнее: https://material.angular.io/cdk/overlay/overview#scroll-strategies
|
|
3117
3198
|
* */
|
|
3118
3199
|
this.scrollStrategy = new NoopScrollStrategy();
|
|
3119
3200
|
this.id = `owl-dialog-${uniqueId++}`;
|
|
@@ -3128,39 +3209,43 @@ class OwlDialogRef {
|
|
|
3128
3209
|
this.overlayRef = overlayRef;
|
|
3129
3210
|
this.container = container;
|
|
3130
3211
|
this.id = id;
|
|
3212
|
+
this.closing = false;
|
|
3131
3213
|
this._beforeClose$ = new Subject();
|
|
3132
3214
|
this._beforeOpen$ = new Subject();
|
|
3133
3215
|
this._afterOpen$ = new Subject();
|
|
3134
3216
|
this._afterClosed$ = new Subject();
|
|
3135
|
-
/**
|
|
3217
|
+
/** Подписка на изменения адреса в браузере */
|
|
3136
3218
|
this.locationChanged = Subscription.EMPTY;
|
|
3137
3219
|
/**
|
|
3138
|
-
*
|
|
3220
|
+
* Экземпляр компонента, открытого в диалоговом окне
|
|
3139
3221
|
* */
|
|
3140
3222
|
this.componentInstance = signal(undefined, /* @ts-ignore */
|
|
3141
3223
|
...(ngDevMode ? [{ debugName: "componentInstance" }] : /* istanbul ignore next */ []));
|
|
3142
|
-
/**
|
|
3224
|
+
/** Разрешено ли пользователю закрывать диалоговое окно */
|
|
3143
3225
|
this.disableClose = true;
|
|
3144
3226
|
this.disableClose = this.container.config.disableClose;
|
|
3145
3227
|
this.container.animationStateChanged
|
|
3146
|
-
.pipe(filter((event) => event.phaseName === 'start' && event.toState === 'enter'), take
|
|
3228
|
+
.pipe(filter((event) => event.phaseName === 'start' && event.toState === 'enter'), take(1))
|
|
3147
3229
|
.subscribe(() => {
|
|
3148
3230
|
this._beforeOpen$.next(null);
|
|
3149
3231
|
this._beforeOpen$.complete();
|
|
3150
3232
|
});
|
|
3151
3233
|
this.container.animationStateChanged
|
|
3152
|
-
.pipe(filter((event) => event.phaseName === 'done' && event.toState === 'enter'), take
|
|
3234
|
+
.pipe(filter((event) => event.phaseName === 'done' && event.toState === 'enter'), take(1))
|
|
3153
3235
|
.subscribe(() => {
|
|
3154
3236
|
this._afterOpen$.next(null);
|
|
3155
3237
|
this._afterOpen$.complete();
|
|
3156
3238
|
});
|
|
3157
3239
|
this.container.animationStateChanged
|
|
3158
|
-
.pipe(filter((event) => event.phaseName === 'done' && event.toState === 'leave'), take
|
|
3240
|
+
.pipe(filter((event) => event.phaseName === 'done' && event.toState === 'leave'), take(1))
|
|
3159
3241
|
.subscribe(() => {
|
|
3160
3242
|
this.overlayRef.dispose();
|
|
3161
3243
|
this.locationChanged.unsubscribe();
|
|
3162
3244
|
this._afterClosed$.next(this.result);
|
|
3163
3245
|
this._afterClosed$.complete();
|
|
3246
|
+
this._beforeOpen$.complete();
|
|
3247
|
+
this._afterOpen$.complete();
|
|
3248
|
+
this._beforeClose$.complete();
|
|
3164
3249
|
this.componentInstance.set(undefined);
|
|
3165
3250
|
});
|
|
3166
3251
|
this.overlayRef.keydownEvents()
|
|
@@ -3175,9 +3260,13 @@ class OwlDialogRef {
|
|
|
3175
3260
|
}
|
|
3176
3261
|
}
|
|
3177
3262
|
close(dialogResult) {
|
|
3263
|
+
if (this.closing) {
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
this.closing = true;
|
|
3178
3267
|
this.result = dialogResult;
|
|
3179
3268
|
this.container.animationStateChanged
|
|
3180
|
-
.pipe(filter(event => event.phaseName === 'start'), take
|
|
3269
|
+
.pipe(filter(event => event.phaseName === 'start' && event.toState === 'leave'), take(1))
|
|
3181
3270
|
.subscribe(() => {
|
|
3182
3271
|
this._beforeClose$.next(dialogResult);
|
|
3183
3272
|
this._beforeClose$.complete();
|
|
@@ -3186,20 +3275,20 @@ class OwlDialogRef {
|
|
|
3186
3275
|
this.container.startExitAnimation();
|
|
3187
3276
|
}
|
|
3188
3277
|
/**
|
|
3189
|
-
*
|
|
3278
|
+
* Возвращает Observable нажатий на фон overlay
|
|
3190
3279
|
*/
|
|
3191
3280
|
backdropClick() {
|
|
3192
3281
|
return this.overlayRef.backdropClick();
|
|
3193
3282
|
}
|
|
3194
3283
|
/**
|
|
3195
|
-
*
|
|
3284
|
+
* Возвращает Observable событий keydown, направленных на overlay
|
|
3196
3285
|
*/
|
|
3197
3286
|
keydownEvents() {
|
|
3198
3287
|
return this.overlayRef.keydownEvents();
|
|
3199
3288
|
}
|
|
3200
3289
|
/**
|
|
3201
|
-
*
|
|
3202
|
-
* @param position
|
|
3290
|
+
* Обновляет положение диалогового окна
|
|
3291
|
+
* @param position Новое положение диалогового окна
|
|
3203
3292
|
*/
|
|
3204
3293
|
updatePosition(position) {
|
|
3205
3294
|
const strategy = this.getPositionStrategy();
|
|
@@ -3219,9 +3308,9 @@ class OwlDialogRef {
|
|
|
3219
3308
|
return this;
|
|
3220
3309
|
}
|
|
3221
3310
|
/**
|
|
3222
|
-
*
|
|
3223
|
-
* @param width
|
|
3224
|
-
* @param height
|
|
3311
|
+
* Обновляет ширину и высоту диалогового окна
|
|
3312
|
+
* @param width Новая ширина диалогового окна
|
|
3313
|
+
* @param height Новая высота диалогового окна
|
|
3225
3314
|
*/
|
|
3226
3315
|
updateSize(width = 'auto', height = 'auto') {
|
|
3227
3316
|
this.getPositionStrategy().width(width).height(height);
|
|
@@ -3243,7 +3332,7 @@ class OwlDialogRef {
|
|
|
3243
3332
|
afterClosed() {
|
|
3244
3333
|
return this._afterClosed$.asObservable();
|
|
3245
3334
|
}
|
|
3246
|
-
/**
|
|
3335
|
+
/** Возвращает стратегию позиционирования из ссылки на overlay */
|
|
3247
3336
|
getPositionStrategy() {
|
|
3248
3337
|
return this.overlayRef.getConfig().positionStrategy;
|
|
3249
3338
|
}
|
|
@@ -3280,13 +3369,16 @@ class OwlDialogContainerComponent extends BasePortalOutlet {
|
|
|
3280
3369
|
this.focusTrapFactory = focusTrapFactory;
|
|
3281
3370
|
this.document = document;
|
|
3282
3371
|
this.portalOutlet = null;
|
|
3283
|
-
|
|
3372
|
+
this.contentAnimationSubscription = Subscription.EMPTY;
|
|
3373
|
+
this.exiting = false;
|
|
3374
|
+
this.destroyed = false;
|
|
3375
|
+
/** ID элемента, используемого как заголовок диалогового окна */
|
|
3284
3376
|
this.ariaLabelledBy = null;
|
|
3285
|
-
/**
|
|
3377
|
+
/** Событие изменения состояния анимации */
|
|
3286
3378
|
this.animationStateChanged = new EventEmitter();
|
|
3287
3379
|
this.isAnimating = signal(false, /* @ts-ignore */
|
|
3288
3380
|
...(ngDevMode ? [{ debugName: "isAnimating" }] : /* istanbul ignore next */ []));
|
|
3289
|
-
//
|
|
3381
|
+
// Для анимации
|
|
3290
3382
|
this.params = {
|
|
3291
3383
|
x: '0px',
|
|
3292
3384
|
y: '0px',
|
|
@@ -3294,13 +3386,19 @@ class OwlDialogContainerComponent extends BasePortalOutlet {
|
|
|
3294
3386
|
oy: '50%',
|
|
3295
3387
|
scale: 0
|
|
3296
3388
|
};
|
|
3297
|
-
//
|
|
3298
|
-
//
|
|
3389
|
+
// Сохраняет элемент, находившийся в фокусе до открытия диалогового окна
|
|
3390
|
+
// Позволяет вернуть фокус на этот элемент после закрытия окна
|
|
3299
3391
|
this.elementFocusedBeforeDialogWasOpened = null;
|
|
3300
3392
|
}
|
|
3301
3393
|
ngOnInit() { }
|
|
3394
|
+
ngOnDestroy() {
|
|
3395
|
+
this.destroyed = true;
|
|
3396
|
+
this.contentAnimationSubscription.unsubscribe();
|
|
3397
|
+
this.restoreFocus();
|
|
3398
|
+
this.animationStateChanged.complete();
|
|
3399
|
+
}
|
|
3302
3400
|
/**
|
|
3303
|
-
*
|
|
3401
|
+
* Подключает ComponentPortal как содержимое контейнера диалогового окна
|
|
3304
3402
|
*/
|
|
3305
3403
|
attachComponentPortal(portal) {
|
|
3306
3404
|
if (this.portalOutlet.hasAttached()) {
|
|
@@ -3309,7 +3407,14 @@ class OwlDialogContainerComponent extends BasePortalOutlet {
|
|
|
3309
3407
|
this.savePreviouslyFocusedElement();
|
|
3310
3408
|
const component = this.portalOutlet.attachComponentPortal(portal);
|
|
3311
3409
|
const pickerContainer = component.instance;
|
|
3312
|
-
pickerContainer.animationStateChanged.subscribe(state =>
|
|
3410
|
+
this.contentAnimationSubscription = pickerContainer.animationStateChanged.subscribe(state => {
|
|
3411
|
+
if (state.phaseName === 'start') {
|
|
3412
|
+
this.onAnimationStart(state);
|
|
3413
|
+
}
|
|
3414
|
+
else {
|
|
3415
|
+
this.onAnimationDone(state);
|
|
3416
|
+
}
|
|
3417
|
+
});
|
|
3313
3418
|
this._component = component;
|
|
3314
3419
|
return component;
|
|
3315
3420
|
}
|
|
@@ -3319,14 +3424,20 @@ class OwlDialogContainerComponent extends BasePortalOutlet {
|
|
|
3319
3424
|
setConfig(config) {
|
|
3320
3425
|
this._config = config;
|
|
3321
3426
|
if (config.event) {
|
|
3322
|
-
this.calculateZoomOrigin(event);
|
|
3427
|
+
this.calculateZoomOrigin(config.event);
|
|
3323
3428
|
}
|
|
3324
3429
|
}
|
|
3325
3430
|
onAnimationStart(event) {
|
|
3431
|
+
if (this.exiting && event.toState === 'enter') {
|
|
3432
|
+
return;
|
|
3433
|
+
}
|
|
3326
3434
|
this.isAnimating.set(true);
|
|
3327
3435
|
this.animationStateChanged.emit(event);
|
|
3328
3436
|
}
|
|
3329
3437
|
onAnimationDone(event) {
|
|
3438
|
+
if (this.exiting && event.toState === 'enter') {
|
|
3439
|
+
return;
|
|
3440
|
+
}
|
|
3330
3441
|
if (event.toState === 'enter') {
|
|
3331
3442
|
this.trapFocus();
|
|
3332
3443
|
}
|
|
@@ -3337,11 +3448,12 @@ class OwlDialogContainerComponent extends BasePortalOutlet {
|
|
|
3337
3448
|
this.isAnimating.set(false);
|
|
3338
3449
|
}
|
|
3339
3450
|
startExitAnimation() {
|
|
3451
|
+
this.exiting = true;
|
|
3340
3452
|
this._component.destroy();
|
|
3341
3453
|
}
|
|
3342
3454
|
/**
|
|
3343
|
-
*
|
|
3344
|
-
*
|
|
3455
|
+
* Вычисляет точку начала, используемую в `zoomFadeInFrom()`,
|
|
3456
|
+
* Для анимации
|
|
3345
3457
|
*/
|
|
3346
3458
|
calculateZoomOrigin(event) {
|
|
3347
3459
|
if (!event) {
|
|
@@ -3363,13 +3475,17 @@ class OwlDialogContainerComponent extends BasePortalOutlet {
|
|
|
3363
3475
|
return;
|
|
3364
3476
|
}
|
|
3365
3477
|
/**
|
|
3366
|
-
*
|
|
3478
|
+
* Сохраняет элемент, находившийся в фокусе до открытия диалогового окна
|
|
3367
3479
|
*/
|
|
3368
3480
|
savePreviouslyFocusedElement() {
|
|
3369
3481
|
if (this.document) {
|
|
3370
3482
|
this.elementFocusedBeforeDialogWasOpened = this.document
|
|
3371
3483
|
.activeElement;
|
|
3372
|
-
Promise.resolve().then(() =>
|
|
3484
|
+
Promise.resolve().then(() => {
|
|
3485
|
+
if (!this.destroyed && !this.exiting) {
|
|
3486
|
+
this.elementRef.nativeElement.focus();
|
|
3487
|
+
}
|
|
3488
|
+
});
|
|
3373
3489
|
}
|
|
3374
3490
|
}
|
|
3375
3491
|
trapFocus() {
|
|
@@ -3382,13 +3498,17 @@ class OwlDialogContainerComponent extends BasePortalOutlet {
|
|
|
3382
3498
|
}
|
|
3383
3499
|
restoreFocus() {
|
|
3384
3500
|
const toFocus = this.elementFocusedBeforeDialogWasOpened;
|
|
3385
|
-
//
|
|
3386
|
-
|
|
3501
|
+
// Дополнительная проверка нужна, поскольку IE иногда задаёт `activeElement` равным null
|
|
3502
|
+
const activeElement = this.document?.activeElement;
|
|
3503
|
+
if (toFocus && typeof toFocus.focus === 'function' &&
|
|
3504
|
+
(!activeElement || activeElement === this.document.body || this.elementRef.nativeElement.contains(activeElement))) {
|
|
3387
3505
|
toFocus.focus();
|
|
3388
3506
|
}
|
|
3389
3507
|
if (this.focusTrap) {
|
|
3390
3508
|
this.focusTrap.destroy();
|
|
3509
|
+
this.focusTrap = null;
|
|
3391
3510
|
}
|
|
3511
|
+
this.elementFocusedBeforeDialogWasOpened = null;
|
|
3392
3512
|
}
|
|
3393
3513
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlDialogContainerComponent, deps: [{ token: i0.ElementRef }, { token: i1.FocusTrapFactory }, { token: DOCUMENT, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3394
3514
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: OwlDialogContainerComponent, isStandalone: false, selector: "owl-dialog-container", host: { properties: { "class.owl-dialog-container": "owlDialogContainerClass", "attr.tabindex": "owlDialogContainerTabIndex", "attr.id": "owlDialogContainerId", "attr.role": "owlDialogContainerRole", "attr.aria-labelledby": "owlDialogContainerAriaLabelledby", "attr.aria-describedby": "owlDialogContainerAriaDescribedby" } }, viewQueries: [{ propertyName: "portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ng-template [cdkPortalOutlet]></ng-template>\r\n", dependencies: [{ kind: "directive", type: i2$1.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] }); }
|
|
@@ -3417,11 +3537,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
3417
3537
|
* object.utils
|
|
3418
3538
|
*/
|
|
3419
3539
|
/**
|
|
3420
|
-
*
|
|
3421
|
-
*
|
|
3540
|
+
* Дополняет объект собственными перечисляемыми свойствами одного или нескольких исходных объектов,
|
|
3541
|
+
* аналогично Object.assign
|
|
3422
3542
|
*
|
|
3423
|
-
* @param dest
|
|
3424
|
-
* @param sources
|
|
3543
|
+
* @param dest Объект, в который копируются свойства
|
|
3544
|
+
* @param sources Исходные объекты, из которых копируются свойства
|
|
3425
3545
|
*/
|
|
3426
3546
|
function extendObject(dest, ...sources) {
|
|
3427
3547
|
if (dest == null) {
|
|
@@ -3430,7 +3550,7 @@ function extendObject(dest, ...sources) {
|
|
|
3430
3550
|
for (const source of sources) {
|
|
3431
3551
|
if (source != null) {
|
|
3432
3552
|
for (const key in source) {
|
|
3433
|
-
if (
|
|
3553
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
3434
3554
|
dest[key] = source[key];
|
|
3435
3555
|
}
|
|
3436
3556
|
}
|
|
@@ -3448,7 +3568,7 @@ function extendObject(dest, ...sources) {
|
|
|
3448
3568
|
*/
|
|
3449
3569
|
const OWL_DIALOG_DATA = new InjectionToken('OwlDialogData');
|
|
3450
3570
|
/**
|
|
3451
|
-
*
|
|
3571
|
+
* Токен DI, определяющий обработку прокрутки при открытом диалоговом окне
|
|
3452
3572
|
* */
|
|
3453
3573
|
const OWL_DIALOG_SCROLL_STRATEGY = new InjectionToken('owl-dialog-scroll-strategy');
|
|
3454
3574
|
function OWL_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) {
|
|
@@ -3462,23 +3582,26 @@ const OWL_DIALOG_SCROLL_STRATEGY_PROVIDER = {
|
|
|
3462
3582
|
useFactory: OWL_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY
|
|
3463
3583
|
};
|
|
3464
3584
|
/**
|
|
3465
|
-
*
|
|
3585
|
+
* Токен DI для задания параметров диалогового окна по умолчанию
|
|
3466
3586
|
* */
|
|
3467
3587
|
const OWL_DIALOG_DEFAULT_OPTIONS = new InjectionToken('owl-dialog-default-options');
|
|
3468
3588
|
class OwlDialogService {
|
|
3469
|
-
|
|
3589
|
+
get ariaHiddenElements() {
|
|
3590
|
+
return this.parentDialog ? this.parentDialog.ariaHiddenElements : this._ariaHiddenElements;
|
|
3591
|
+
}
|
|
3592
|
+
/** Хранит текущие открытые диалоговые окна */
|
|
3470
3593
|
get openDialogs() {
|
|
3471
3594
|
return this.parentDialog
|
|
3472
3595
|
? this.parentDialog.openDialogs
|
|
3473
3596
|
: this._openDialogsAtThisLevel;
|
|
3474
3597
|
}
|
|
3475
|
-
/**
|
|
3598
|
+
/** Поток событий открытия диалогового окна */
|
|
3476
3599
|
get beforeOpen() {
|
|
3477
3600
|
return this.parentDialog
|
|
3478
3601
|
? this.parentDialog.beforeOpen
|
|
3479
3602
|
: this._beforeOpenAtThisLevel;
|
|
3480
3603
|
}
|
|
3481
|
-
/**
|
|
3604
|
+
/** Поток событий открытия диалогового окна */
|
|
3482
3605
|
get afterOpen() {
|
|
3483
3606
|
return this.parentDialog
|
|
3484
3607
|
? this.parentDialog.afterOpen
|
|
@@ -3497,22 +3620,19 @@ class OwlDialogService {
|
|
|
3497
3620
|
this.defaultOptions = defaultOptions;
|
|
3498
3621
|
this.parentDialog = parentDialog;
|
|
3499
3622
|
this.overlayContainer = overlayContainer;
|
|
3500
|
-
this.
|
|
3623
|
+
this._ariaHiddenElements = new Map();
|
|
3501
3624
|
this._openDialogsAtThisLevel = [];
|
|
3502
3625
|
this._beforeOpenAtThisLevel = new Subject();
|
|
3503
3626
|
this._afterOpenAtThisLevel = new Subject();
|
|
3504
3627
|
this._afterAllClosedAtThisLevel = new Subject();
|
|
3505
3628
|
/**
|
|
3506
|
-
*
|
|
3507
|
-
*
|
|
3629
|
+
* Поток событий завершения закрытия всех диалоговых окон
|
|
3630
|
+
* Если открытых окон нет, событие отправляется сразу при подписке
|
|
3508
3631
|
*/
|
|
3509
|
-
this.afterAllClosed = defer(() => this.
|
|
3632
|
+
this.afterAllClosed = defer(() => this.openDialogs.length
|
|
3510
3633
|
? this._afterAllClosed
|
|
3511
3634
|
: this._afterAllClosed.pipe(startWith(undefined)));
|
|
3512
3635
|
this.scrollStrategy = scrollStrategy;
|
|
3513
|
-
if (!parentDialog && location) {
|
|
3514
|
-
location.subscribe(() => this.closeAll());
|
|
3515
|
-
}
|
|
3516
3636
|
}
|
|
3517
3637
|
open(componentOrTemplateRef, config) {
|
|
3518
3638
|
config = applyConfigDefaults(config, this.defaultOptions);
|
|
@@ -3534,7 +3654,7 @@ class OwlDialogService {
|
|
|
3534
3654
|
return dialogRef;
|
|
3535
3655
|
}
|
|
3536
3656
|
/**
|
|
3537
|
-
*
|
|
3657
|
+
* Закрывает все открытые диалоговые окна
|
|
3538
3658
|
*/
|
|
3539
3659
|
closeAll() {
|
|
3540
3660
|
let i = this.openDialogs.length;
|
|
@@ -3543,8 +3663,8 @@ class OwlDialogService {
|
|
|
3543
3663
|
}
|
|
3544
3664
|
}
|
|
3545
3665
|
/**
|
|
3546
|
-
*
|
|
3547
|
-
* @param id ID
|
|
3666
|
+
* Находит открытое диалоговое окно по ID
|
|
3667
|
+
* @param id ID искомого диалогового окна
|
|
3548
3668
|
*/
|
|
3549
3669
|
getDialogById(id) {
|
|
3550
3670
|
return this.openDialogs.find(dialog => dialog.id === id);
|
|
@@ -3609,11 +3729,11 @@ class OwlDialogService {
|
|
|
3609
3729
|
return state;
|
|
3610
3730
|
}
|
|
3611
3731
|
removeOpenDialog(dialogRef) {
|
|
3612
|
-
const index = this.
|
|
3732
|
+
const index = this.openDialogs.indexOf(dialogRef);
|
|
3613
3733
|
if (index > -1) {
|
|
3614
3734
|
this.openDialogs.splice(index, 1);
|
|
3615
|
-
//
|
|
3616
|
-
//
|
|
3735
|
+
// Если все диалоговые окна закрыты, удаляем или восстанавливаем `aria-hidden`
|
|
3736
|
+
// у соседних элементов и отправляем событие в поток `afterAllClosed`
|
|
3617
3737
|
if (!this.openDialogs.length) {
|
|
3618
3738
|
this.ariaHiddenElements.forEach((previousValue, element) => {
|
|
3619
3739
|
if (previousValue) {
|
|
@@ -3629,11 +3749,11 @@ class OwlDialogService {
|
|
|
3629
3749
|
}
|
|
3630
3750
|
}
|
|
3631
3751
|
/**
|
|
3632
|
-
*
|
|
3752
|
+
* Скрывает от вспомогательных технологий всё содержимое за пределами overlay
|
|
3633
3753
|
*/
|
|
3634
3754
|
hideNonDialogContentFromAssistiveTechnology() {
|
|
3635
3755
|
const overlayContainer = this.overlayContainer.getContainerElement();
|
|
3636
|
-
//
|
|
3756
|
+
// Проверяем, что контейнер overlay подключён к DOM
|
|
3637
3757
|
if (overlayContainer.parentElement) {
|
|
3638
3758
|
const siblings = overlayContainer.parentElement.children;
|
|
3639
3759
|
for (let i = siblings.length - 1; i > -1; i--) {
|
|
@@ -3669,19 +3789,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
3669
3789
|
type: SkipSelf
|
|
3670
3790
|
}] }, { type: i1$1.OverlayContainer }] });
|
|
3671
3791
|
/**
|
|
3672
|
-
*
|
|
3673
|
-
* @param config
|
|
3674
|
-
* @param defaultOptions
|
|
3675
|
-
* @returns
|
|
3792
|
+
* Применяет параметры по умолчанию к конфигурации диалогового окна
|
|
3793
|
+
* @param config Изменяемая конфигурация
|
|
3794
|
+
* @param defaultOptions Параметры конфигурации по умолчанию
|
|
3795
|
+
* @returns Новый объект конфигурации
|
|
3676
3796
|
*/
|
|
3677
3797
|
function applyConfigDefaults(config, defaultOptions) {
|
|
3678
|
-
return extendObject(new OwlDialogConfig(),
|
|
3798
|
+
return extendObject(new OwlDialogConfig(), defaultOptions, config);
|
|
3679
3799
|
}
|
|
3680
3800
|
|
|
3681
3801
|
/**
|
|
3682
3802
|
* date-time-picker.component
|
|
3683
3803
|
*/
|
|
3684
|
-
/**
|
|
3804
|
+
/** Токен DI, определяющий обработку прокрутки при открытом компоненте выбора даты и времени */
|
|
3685
3805
|
const OWL_DTPICKER_SCROLL_STRATEGY = new InjectionToken('owl-dtpicker-scroll-strategy');
|
|
3686
3806
|
/** @docs-private */
|
|
3687
3807
|
function OWL_DTPICKER_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) {
|
|
@@ -3696,21 +3816,21 @@ const OWL_DTPICKER_SCROLL_STRATEGY_PROVIDER = {
|
|
|
3696
3816
|
};
|
|
3697
3817
|
class OwlDateTimeComponent extends OwlDateTime {
|
|
3698
3818
|
get startAt() {
|
|
3699
|
-
//
|
|
3700
|
-
//
|
|
3701
|
-
if (this._startAt) {
|
|
3819
|
+
// Если startAt задан явно, открываем календарь на этой дате
|
|
3820
|
+
// Иначе используем текущее выбранное значение
|
|
3821
|
+
if (this._startAt != null) {
|
|
3702
3822
|
return this._startAt;
|
|
3703
3823
|
}
|
|
3704
3824
|
if (this._dtInput) {
|
|
3705
3825
|
if (this._dtInput.selectMode === 'single') {
|
|
3706
|
-
return this._dtInput.value
|
|
3826
|
+
return this._dtInput.value ?? null;
|
|
3707
3827
|
}
|
|
3708
3828
|
else if (this._dtInput.selectMode === 'range' ||
|
|
3709
3829
|
this._dtInput.selectMode === 'rangeFrom') {
|
|
3710
|
-
return this._dtInput.values[0]
|
|
3830
|
+
return this._dtInput.values[0] ?? null;
|
|
3711
3831
|
}
|
|
3712
3832
|
else if (this._dtInput.selectMode === 'rangeTo') {
|
|
3713
|
-
return this._dtInput.values[1]
|
|
3833
|
+
return this._dtInput.values[1] ?? null;
|
|
3714
3834
|
}
|
|
3715
3835
|
}
|
|
3716
3836
|
else {
|
|
@@ -3721,16 +3841,16 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
3721
3841
|
this._startAt = this.getValidDate(this.dateTimeAdapter.deserialize(date));
|
|
3722
3842
|
}
|
|
3723
3843
|
get endAt() {
|
|
3724
|
-
if (this._endAt) {
|
|
3844
|
+
if (this._endAt != null) {
|
|
3725
3845
|
return this._endAt;
|
|
3726
3846
|
}
|
|
3727
3847
|
if (this._dtInput) {
|
|
3728
3848
|
if (this._dtInput.selectMode === 'single') {
|
|
3729
|
-
return this._dtInput.value
|
|
3849
|
+
return this._dtInput.value ?? null;
|
|
3730
3850
|
}
|
|
3731
3851
|
else if (this._dtInput.selectMode === 'range' ||
|
|
3732
3852
|
this._dtInput.selectMode === 'rangeFrom') {
|
|
3733
|
-
return this._dtInput.values[1]
|
|
3853
|
+
return this._dtInput.values[1] ?? null;
|
|
3734
3854
|
}
|
|
3735
3855
|
}
|
|
3736
3856
|
else {
|
|
@@ -3772,6 +3892,7 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
3772
3892
|
if (value !== this._disabled) {
|
|
3773
3893
|
this._disabled = value;
|
|
3774
3894
|
this.disabledChange.next(value);
|
|
3895
|
+
this.refreshView();
|
|
3775
3896
|
}
|
|
3776
3897
|
}
|
|
3777
3898
|
get opened() {
|
|
@@ -3788,20 +3909,20 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
3788
3909
|
}
|
|
3789
3910
|
set selected(value) {
|
|
3790
3911
|
this._selected = value;
|
|
3791
|
-
this.
|
|
3912
|
+
this.refreshView();
|
|
3792
3913
|
}
|
|
3793
3914
|
get selecteds() {
|
|
3794
3915
|
return this._selecteds;
|
|
3795
3916
|
}
|
|
3796
3917
|
set selecteds(values) {
|
|
3797
3918
|
this._selecteds = values;
|
|
3798
|
-
this.
|
|
3919
|
+
this.refreshView();
|
|
3799
3920
|
}
|
|
3800
|
-
/**
|
|
3921
|
+
/** Минимальная доступная для выбора дата */
|
|
3801
3922
|
get minDateTime() {
|
|
3802
3923
|
return this._dtInput && this._dtInput.min;
|
|
3803
3924
|
}
|
|
3804
|
-
/**
|
|
3925
|
+
/** Максимальная доступная для выбора дата */
|
|
3805
3926
|
get maxDateTime() {
|
|
3806
3927
|
return this._dtInput && this._dtInput.max;
|
|
3807
3928
|
}
|
|
@@ -3827,69 +3948,78 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
3827
3948
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
3828
3949
|
this.dateTimeFormats = dateTimeFormats;
|
|
3829
3950
|
this.document = document;
|
|
3830
|
-
/**
|
|
3951
|
+
/** Пользовательский класс фона компонента выбора */
|
|
3831
3952
|
this.backdropClass = [];
|
|
3832
|
-
/**
|
|
3953
|
+
/** Пользовательский класс overlay-панели компонента выбора */
|
|
3833
3954
|
this.panelClass = [];
|
|
3834
3955
|
/**
|
|
3835
|
-
*
|
|
3836
|
-
* 'both'
|
|
3837
|
-
* 'calendar'
|
|
3838
|
-
* 'timer'
|
|
3956
|
+
* Задаёт тип компонента выбора даты и времени:
|
|
3957
|
+
* 'both' — календарь и выбор времени
|
|
3958
|
+
* 'calendar' — только календарь
|
|
3959
|
+
* 'timer' — только выбор времени
|
|
3839
3960
|
*/
|
|
3840
3961
|
this._pickerType = 'both';
|
|
3841
3962
|
/**
|
|
3842
|
-
*
|
|
3963
|
+
* Открывается ли компонент выбора в диалоговом окне
|
|
3843
3964
|
*/
|
|
3844
3965
|
this._pickerMode = 'popup';
|
|
3845
|
-
/**
|
|
3966
|
+
/** Открыт ли календарь */
|
|
3846
3967
|
this._opened = false;
|
|
3968
|
+
this.closing = false;
|
|
3969
|
+
this.destroyed = false;
|
|
3970
|
+
this.injector = inject(Injector);
|
|
3847
3971
|
/**
|
|
3848
|
-
*
|
|
3972
|
+
* Обработчик закрытия компонента выбора
|
|
3849
3973
|
* */
|
|
3850
3974
|
this.afterPickerClosed = new EventEmitter();
|
|
3851
3975
|
/**
|
|
3852
|
-
*
|
|
3976
|
+
* Обработчик перед открытием компонента выбора
|
|
3853
3977
|
* */
|
|
3854
3978
|
this.beforePickerOpen = new EventEmitter();
|
|
3855
3979
|
/**
|
|
3856
|
-
*
|
|
3980
|
+
* Обработчик открытия компонента выбора
|
|
3857
3981
|
* */
|
|
3858
3982
|
this.afterPickerOpen = new EventEmitter();
|
|
3859
3983
|
/**
|
|
3860
|
-
*
|
|
3861
|
-
*
|
|
3984
|
+
* Передаёт выбранный год в представлении нескольких лет
|
|
3985
|
+
* При этом выбранная дата не изменяется
|
|
3862
3986
|
* */
|
|
3863
3987
|
this.yearSelected = new EventEmitter();
|
|
3864
3988
|
/**
|
|
3865
|
-
*
|
|
3866
|
-
*
|
|
3989
|
+
* Передаёт выбранный месяц в представлении года
|
|
3990
|
+
* При этом выбранная дата не изменяется
|
|
3867
3991
|
* */
|
|
3868
3992
|
this.monthSelected = new EventEmitter();
|
|
3869
3993
|
/**
|
|
3870
|
-
*
|
|
3994
|
+
* Передаёт выбранную дату
|
|
3871
3995
|
* */
|
|
3872
3996
|
this.dateSelected = new EventEmitter();
|
|
3873
3997
|
/**
|
|
3874
|
-
*
|
|
3998
|
+
* Событие подтверждения выбранного значения
|
|
3875
3999
|
* */
|
|
3876
4000
|
this.confirmSelectedChange = new EventEmitter();
|
|
3877
4001
|
/**
|
|
3878
|
-
*
|
|
4002
|
+
* Событие отключения компонента выбора даты и времени
|
|
3879
4003
|
* */
|
|
3880
4004
|
this.disabledChange = new EventEmitter();
|
|
4005
|
+
this.dialogClosedStreamSub = Subscription.EMPTY;
|
|
3881
4006
|
this.dtInputSub = Subscription.EMPTY;
|
|
3882
4007
|
this.hidePickerStreamSub = Subscription.EMPTY;
|
|
3883
4008
|
this.confirmSelectedStreamSub = Subscription.EMPTY;
|
|
3884
4009
|
this.pickerOpenedStreamSub = Subscription.EMPTY;
|
|
3885
4010
|
this.pickerBeforeOpenedStreamSub = Subscription.EMPTY;
|
|
3886
|
-
/**
|
|
4011
|
+
/** Элемент, находившийся в фокусе до открытия компонента выбора даты и времени */
|
|
3887
4012
|
this.focusedElementBeforeOpen = null;
|
|
3888
4013
|
this._selecteds = [];
|
|
3889
4014
|
this.defaultScrollStrategy = defaultScrollStrategy;
|
|
3890
4015
|
}
|
|
4016
|
+
refreshView() {
|
|
4017
|
+
this.changeDetector.markForCheck();
|
|
4018
|
+
this.pickerContainer?.refreshView();
|
|
4019
|
+
}
|
|
3891
4020
|
ngOnInit() { }
|
|
3892
4021
|
ngOnDestroy() {
|
|
4022
|
+
this.destroyed = true;
|
|
3893
4023
|
this.close();
|
|
3894
4024
|
this.dtInputSub.unsubscribe();
|
|
3895
4025
|
this.disabledChange.complete();
|
|
@@ -3912,7 +4042,7 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
3912
4042
|
});
|
|
3913
4043
|
}
|
|
3914
4044
|
open() {
|
|
3915
|
-
if (this._opened || this.disabled) {
|
|
4045
|
+
if (this._opened || this.closing || this.destroyed || this.disabled) {
|
|
3916
4046
|
return;
|
|
3917
4047
|
}
|
|
3918
4048
|
if (!this._dtInput) {
|
|
@@ -3921,31 +4051,33 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
3921
4051
|
if (this.document) {
|
|
3922
4052
|
this.focusedElementBeforeOpen = this.document.activeElement;
|
|
3923
4053
|
}
|
|
3924
|
-
//
|
|
4054
|
+
// Сбрасываем выбранное значение компонента
|
|
3925
4055
|
if (this.isInSingleMode) {
|
|
3926
4056
|
this.selected = this._dtInput.value;
|
|
3927
4057
|
}
|
|
3928
4058
|
else if (this.isInRangeMode) {
|
|
3929
4059
|
this.selecteds = this._dtInput.values;
|
|
3930
4060
|
}
|
|
3931
|
-
//
|
|
3932
|
-
//
|
|
3933
|
-
if (this.selected && this.pickerType !== 'calendar' && this._startAt) {
|
|
4061
|
+
// При открытии компонента выбора приводим текущее выбранное время
|
|
4062
|
+
// к времени из _startAt
|
|
4063
|
+
if (this.selected != null && this.pickerType !== 'calendar' && this._startAt != null) {
|
|
3934
4064
|
this.selected = this.dateTimeAdapter.createDate(this.dateTimeAdapter.getYear(this.selected), this.dateTimeAdapter.getMonth(this.selected), this.dateTimeAdapter.getDate(this.selected), this.dateTimeAdapter.getHours(this._startAt), this.dateTimeAdapter.getMinutes(this._startAt), this.dateTimeAdapter.getSeconds(this._startAt));
|
|
3935
4065
|
}
|
|
4066
|
+
this._opened = true;
|
|
4067
|
+
this.changeDetector.markForCheck();
|
|
3936
4068
|
this.pickerMode === 'dialog' ? this.openAsDialog() : this.openAsPopup();
|
|
3937
4069
|
this.pickerContainer.picker = this;
|
|
3938
|
-
//
|
|
4070
|
+
// Подписываемся на hidePickerStream контейнера компонента выбора
|
|
3939
4071
|
this.hidePickerStreamSub = this.pickerContainer.hidePickerStream.subscribe(() => {
|
|
3940
4072
|
this.close();
|
|
3941
4073
|
});
|
|
3942
|
-
//
|
|
4074
|
+
// Подписываемся на confirmSelectedStream контейнера компонента выбора
|
|
3943
4075
|
this.confirmSelectedStreamSub = this.pickerContainer.confirmSelectedStream.subscribe((event) => {
|
|
3944
4076
|
this.confirmSelect(event);
|
|
3945
4077
|
});
|
|
3946
4078
|
}
|
|
3947
4079
|
/**
|
|
3948
|
-
*
|
|
4080
|
+
* Выбирает указанную дату
|
|
3949
4081
|
*/
|
|
3950
4082
|
select(date) {
|
|
3951
4083
|
if (Array.isArray(date)) {
|
|
@@ -3955,105 +4087,82 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
3955
4087
|
this.selected = date;
|
|
3956
4088
|
}
|
|
3957
4089
|
/**
|
|
3958
|
-
*
|
|
3959
|
-
* 1)
|
|
3960
|
-
* 2)
|
|
3961
|
-
* 3)
|
|
3962
|
-
*
|
|
3963
|
-
* 4) selectMode
|
|
3964
|
-
* 5) selectMode
|
|
4090
|
+
* Условия автоматического подтверждения выбранной даты или диапазона:
|
|
4091
|
+
* 1) Режим компонента отличается от 'dialog'
|
|
4092
|
+
* 2) Тип компонента — 'calendar', а selectMode — 'single'
|
|
4093
|
+
* 3) Тип компонента — 'calendar', selectMode — 'range',
|
|
4094
|
+
* а в selecteds заданы начало (selecteds[0]) и конец (selecteds[1]) диапазона
|
|
4095
|
+
* 4) selectMode — 'rangeFrom', а selecteds[0] содержит значение
|
|
4096
|
+
* 5) selectMode — 'rangeTo', а selecteds[1] содержит значение
|
|
3965
4097
|
* */
|
|
3966
4098
|
if (this.pickerMode !== 'dialog' &&
|
|
3967
4099
|
this.pickerType === 'calendar' &&
|
|
3968
|
-
((this.selectMode === 'single' && this.selected) ||
|
|
3969
|
-
(this.selectMode === 'rangeFrom' && this.selecteds[0]) ||
|
|
3970
|
-
(this.selectMode === 'rangeTo' && this.selecteds[1]) ||
|
|
4100
|
+
((this.selectMode === 'single' && this.selected != null) ||
|
|
4101
|
+
(this.selectMode === 'rangeFrom' && this.selecteds[0] != null) ||
|
|
4102
|
+
(this.selectMode === 'rangeTo' && this.selecteds[1] != null) ||
|
|
3971
4103
|
(this.selectMode === 'range' &&
|
|
3972
|
-
this.selecteds[0] &&
|
|
3973
|
-
this.selecteds[1]))) {
|
|
4104
|
+
this.selecteds[0] != null &&
|
|
4105
|
+
this.selecteds[1] != null))) {
|
|
3974
4106
|
this.confirmSelect();
|
|
3975
4107
|
}
|
|
3976
4108
|
}
|
|
3977
4109
|
/**
|
|
3978
|
-
*
|
|
4110
|
+
* Передаёт выбранный год в представлении нескольких лет
|
|
3979
4111
|
* */
|
|
3980
4112
|
selectYear(normalizedYear) {
|
|
3981
4113
|
this.yearSelected.emit(normalizedYear);
|
|
3982
4114
|
}
|
|
3983
4115
|
/**
|
|
3984
|
-
*
|
|
4116
|
+
* Передаёт выбранный месяц в представлении года
|
|
3985
4117
|
* */
|
|
3986
4118
|
selectMonth(normalizedMonth) {
|
|
3987
4119
|
this.monthSelected.emit(normalizedMonth);
|
|
3988
4120
|
}
|
|
3989
4121
|
/**
|
|
3990
|
-
*
|
|
4122
|
+
* Передаёт выбранную дату
|
|
3991
4123
|
* */
|
|
3992
4124
|
selectDate(normalizedDate) {
|
|
3993
4125
|
this.dateSelected.emit(normalizedDate);
|
|
3994
4126
|
}
|
|
3995
4127
|
/**
|
|
3996
|
-
*
|
|
4128
|
+
* Закрывает компонент выбора
|
|
3997
4129
|
*/
|
|
3998
4130
|
close() {
|
|
3999
|
-
if (!this._opened) {
|
|
4131
|
+
if (!this._opened || this.closing) {
|
|
4000
4132
|
return;
|
|
4001
4133
|
}
|
|
4002
|
-
|
|
4134
|
+
this.closing = true;
|
|
4135
|
+
this._opened = false;
|
|
4136
|
+
this.positionRenderRef?.destroy();
|
|
4137
|
+
this.positionRenderRef = undefined;
|
|
4138
|
+
this.hidePickerStreamSub?.unsubscribe();
|
|
4139
|
+
this.confirmSelectedStreamSub?.unsubscribe();
|
|
4140
|
+
this.pickerBeforeOpenedStreamSub?.unsubscribe();
|
|
4141
|
+
this.pickerOpenedStreamSub?.unsubscribe();
|
|
4142
|
+
this.dialogClosedStreamSub.unsubscribe();
|
|
4143
|
+
const dialogRef = this.dialogRef;
|
|
4144
|
+
this.dialogRef = null;
|
|
4145
|
+
dialogRef?.close();
|
|
4146
|
+
if (this.popupRef?.hasAttached()) {
|
|
4003
4147
|
this.popupRef.detach();
|
|
4004
4148
|
}
|
|
4005
|
-
if (this.pickerContainerPortal
|
|
4006
|
-
this.pickerContainerPortal.isAttached) {
|
|
4149
|
+
if (this.pickerContainerPortal?.isAttached) {
|
|
4007
4150
|
this.pickerContainerPortal.detach();
|
|
4008
4151
|
}
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
}
|
|
4017
|
-
if (this.pickerBeforeOpenedStreamSub) {
|
|
4018
|
-
this.pickerBeforeOpenedStreamSub.unsubscribe();
|
|
4019
|
-
this.pickerBeforeOpenedStreamSub = null;
|
|
4020
|
-
}
|
|
4021
|
-
if (this.pickerOpenedStreamSub) {
|
|
4022
|
-
this.pickerOpenedStreamSub.unsubscribe();
|
|
4023
|
-
this.pickerOpenedStreamSub = null;
|
|
4024
|
-
}
|
|
4025
|
-
if (this.dialogRef) {
|
|
4026
|
-
this.dialogRef.close();
|
|
4027
|
-
this.dialogRef = null;
|
|
4028
|
-
}
|
|
4029
|
-
const completeClose = () => {
|
|
4030
|
-
if (this._opened) {
|
|
4031
|
-
this._opened = false;
|
|
4032
|
-
const selected = this.selected || this.selecteds;
|
|
4033
|
-
this.afterPickerClosed.emit(selected);
|
|
4034
|
-
this.focusedElementBeforeOpen = null;
|
|
4035
|
-
}
|
|
4036
|
-
};
|
|
4037
|
-
if (this.focusedElementBeforeOpen &&
|
|
4038
|
-
typeof this.focusedElementBeforeOpen.focus === 'function') {
|
|
4039
|
-
// Because IE moves focus asynchronously, we can't count on it being restored before we've
|
|
4040
|
-
// marked the datepicker as closed. If the event fires out of sequence and the element that
|
|
4041
|
-
// we're refocusing opens the datepicker on focus, the user could be stuck with not being
|
|
4042
|
-
// able to close the calendar at all. We work around it by making the logic, that marks
|
|
4043
|
-
// the datepicker as closed, async as well.
|
|
4044
|
-
this.focusedElementBeforeOpen.focus();
|
|
4045
|
-
setTimeout(completeClose);
|
|
4046
|
-
}
|
|
4047
|
-
else {
|
|
4048
|
-
completeClose();
|
|
4049
|
-
}
|
|
4152
|
+
this.pickerContainer = null;
|
|
4153
|
+
// Игнорируем обработчики фокуса, пытающиеся повторно открыть компонент при восстановлении фокуса
|
|
4154
|
+
this.focusedElementBeforeOpen?.focus();
|
|
4155
|
+
this.focusedElementBeforeOpen = null;
|
|
4156
|
+
this.changeDetector.markForCheck();
|
|
4157
|
+
this.closing = false;
|
|
4158
|
+
this.afterPickerClosed.emit(this.isInSingleMode ? this.selected : this.selecteds);
|
|
4050
4159
|
}
|
|
4051
4160
|
/**
|
|
4052
|
-
*
|
|
4161
|
+
* Подтверждает выбранное значение
|
|
4053
4162
|
*/
|
|
4054
4163
|
confirmSelect(event) {
|
|
4055
4164
|
if (this.isInSingleMode) {
|
|
4056
|
-
const selected = this.selected
|
|
4165
|
+
const selected = this.selected ?? this.startAt ?? this.dateTimeAdapter.now();
|
|
4057
4166
|
this.confirmSelectedChange.emit(selected);
|
|
4058
4167
|
}
|
|
4059
4168
|
else if (this.isInRangeMode) {
|
|
@@ -4063,7 +4172,7 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
4063
4172
|
return;
|
|
4064
4173
|
}
|
|
4065
4174
|
/**
|
|
4066
|
-
*
|
|
4175
|
+
* Открывает компонент выбора в диалоговом окне
|
|
4067
4176
|
*/
|
|
4068
4177
|
openAsDialog() {
|
|
4069
4178
|
this.dialogRef = this.dialogService.open(OwlDateTimeContainerComponent, {
|
|
@@ -4077,17 +4186,16 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
4077
4186
|
scrollStrategy: this.scrollStrategy || this.defaultScrollStrategy()
|
|
4078
4187
|
});
|
|
4079
4188
|
this.pickerContainer = untracked(this.dialogRef.componentInstance);
|
|
4080
|
-
this.dialogRef.beforeOpen().subscribe(() => {
|
|
4189
|
+
this.pickerBeforeOpenedStreamSub = this.dialogRef.beforeOpen().subscribe(() => {
|
|
4081
4190
|
this.beforePickerOpen.emit(null);
|
|
4082
4191
|
});
|
|
4083
|
-
this.dialogRef.afterOpen().subscribe(() => {
|
|
4192
|
+
this.pickerOpenedStreamSub = this.dialogRef.afterOpen().subscribe(() => {
|
|
4084
4193
|
this.afterPickerOpen.emit(null);
|
|
4085
|
-
this._opened = true;
|
|
4086
4194
|
});
|
|
4087
|
-
this.dialogRef.afterClosed().subscribe(() => this.close());
|
|
4195
|
+
this.dialogClosedStreamSub = this.dialogRef.afterClosed().subscribe(() => this.close());
|
|
4088
4196
|
}
|
|
4089
4197
|
/**
|
|
4090
|
-
*
|
|
4198
|
+
* Открывает компонент выбора во всплывающем окне
|
|
4091
4199
|
*/
|
|
4092
4200
|
openAsPopup() {
|
|
4093
4201
|
if (!this.pickerContainerPortal) {
|
|
@@ -4099,24 +4207,26 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
4099
4207
|
if (!this.popupRef.hasAttached()) {
|
|
4100
4208
|
const componentRef = this.popupRef.attach(this.pickerContainerPortal);
|
|
4101
4209
|
this.pickerContainer = componentRef.instance;
|
|
4102
|
-
//
|
|
4103
|
-
this.
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4210
|
+
// Обновляем положение после отрисовки календаря
|
|
4211
|
+
this.positionRenderRef?.destroy();
|
|
4212
|
+
this.positionRenderRef = afterNextRender({
|
|
4213
|
+
mixedReadWrite: () => {
|
|
4214
|
+
this.positionRenderRef = undefined;
|
|
4215
|
+
if (this.popupRef.hasAttached()) {
|
|
4216
|
+
this.popupRef.updatePosition();
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
}, { injector: this.injector });
|
|
4109
4220
|
this.pickerBeforeOpenedStreamSub = this.pickerContainer.beforePickerOpenedStream
|
|
4110
|
-
.pipe(take(1))
|
|
4221
|
+
.pipe(take$1(1))
|
|
4111
4222
|
.subscribe(() => {
|
|
4112
4223
|
this.beforePickerOpen.emit(null);
|
|
4113
4224
|
});
|
|
4114
|
-
//
|
|
4225
|
+
// Отправляем событие открытия
|
|
4115
4226
|
this.pickerOpenedStreamSub = this.pickerContainer.pickerOpenedStream
|
|
4116
|
-
.pipe(take(1))
|
|
4227
|
+
.pipe(take$1(1))
|
|
4117
4228
|
.subscribe(() => {
|
|
4118
4229
|
this.afterPickerOpen.emit(null);
|
|
4119
|
-
this._opened = true;
|
|
4120
4230
|
});
|
|
4121
4231
|
}
|
|
4122
4232
|
}
|
|
@@ -4140,7 +4250,7 @@ class OwlDateTimeComponent extends OwlDateTime {
|
|
|
4140
4250
|
event.keyCode === UP_ARROW)))).subscribe(() => this.close());
|
|
4141
4251
|
}
|
|
4142
4252
|
/**
|
|
4143
|
-
*
|
|
4253
|
+
* Создаёт PositionStrategy всплывающего окна
|
|
4144
4254
|
* */
|
|
4145
4255
|
createPopupPositionStrategy() {
|
|
4146
4256
|
return this.overlay
|
|
@@ -4261,21 +4371,22 @@ class OwlDateTimeInputDirective {
|
|
|
4261
4371
|
return this._required;
|
|
4262
4372
|
}
|
|
4263
4373
|
set required(value) {
|
|
4264
|
-
this._required = value
|
|
4374
|
+
this._required = coerceBooleanProperty(value);
|
|
4265
4375
|
this.validatorOnChange();
|
|
4266
4376
|
}
|
|
4267
4377
|
/**
|
|
4268
|
-
*
|
|
4378
|
+
* Компонент выбора даты и времени, связанный с этим полем
|
|
4269
4379
|
* */
|
|
4270
4380
|
set owlDateTime(value) {
|
|
4271
4381
|
this.registerDateTimePicker(value);
|
|
4272
4382
|
}
|
|
4273
4383
|
/**
|
|
4274
|
-
*
|
|
4384
|
+
* Функция фильтрации даты и времени
|
|
4275
4385
|
*/
|
|
4276
4386
|
set owlDateTimeFilter(filter) {
|
|
4277
4387
|
this._dateTimeFilter = filter;
|
|
4278
4388
|
this.validatorOnChange();
|
|
4389
|
+
this.dtPicker?.refreshView();
|
|
4279
4390
|
}
|
|
4280
4391
|
get dateTimeFilter() {
|
|
4281
4392
|
return this._dateTimeFilter;
|
|
@@ -4289,12 +4400,14 @@ class OwlDateTimeInputDirective {
|
|
|
4289
4400
|
if (this._disabled !== newValue) {
|
|
4290
4401
|
this._disabled = newValue;
|
|
4291
4402
|
this.disabledChange.emit(newValue);
|
|
4403
|
+
this.changeDetector.markForCheck();
|
|
4404
|
+
this.dtPicker?.refreshView();
|
|
4292
4405
|
}
|
|
4293
|
-
//
|
|
4406
|
+
// Проверяем наличие метода `blur`, поскольку при SSR он отсутствует
|
|
4294
4407
|
if (newValue && element.blur) {
|
|
4295
|
-
//
|
|
4296
|
-
//
|
|
4297
|
-
//
|
|
4408
|
+
// Обычно нативное поле ввода автоматически теряет фокус при отключении, что
|
|
4409
|
+
// запускает дополнительный цикл change detection и может вызвать ошибку
|
|
4410
|
+
// changed after checked, если поле ввода до этого находилось в фокусе
|
|
4298
4411
|
element.blur();
|
|
4299
4412
|
}
|
|
4300
4413
|
}
|
|
@@ -4304,6 +4417,7 @@ class OwlDateTimeInputDirective {
|
|
|
4304
4417
|
set min(value) {
|
|
4305
4418
|
this._min = this.getValidDate(this.dateTimeAdapter.deserialize(value));
|
|
4306
4419
|
this.validatorOnChange();
|
|
4420
|
+
this.dtPicker?.refreshView();
|
|
4307
4421
|
}
|
|
4308
4422
|
get max() {
|
|
4309
4423
|
return this._max;
|
|
@@ -4311,6 +4425,7 @@ class OwlDateTimeInputDirective {
|
|
|
4311
4425
|
set max(value) {
|
|
4312
4426
|
this._max = this.getValidDate(this.dateTimeAdapter.deserialize(value));
|
|
4313
4427
|
this.validatorOnChange();
|
|
4428
|
+
this.dtPicker?.refreshView();
|
|
4314
4429
|
}
|
|
4315
4430
|
get selectMode() {
|
|
4316
4431
|
return this._selectMode;
|
|
@@ -4323,19 +4438,21 @@ class OwlDateTimeInputDirective {
|
|
|
4323
4438
|
throw Error('OwlDateTime Error: invalid selectMode value!');
|
|
4324
4439
|
}
|
|
4325
4440
|
this._selectMode = mode;
|
|
4441
|
+
this.validatorOnChange();
|
|
4442
|
+
this.dtPicker?.refreshView();
|
|
4326
4443
|
}
|
|
4327
4444
|
get value() {
|
|
4328
4445
|
return this._value;
|
|
4329
4446
|
}
|
|
4330
4447
|
set value(value) {
|
|
4331
4448
|
value = this.dateTimeAdapter.deserialize(value);
|
|
4332
|
-
this.lastValueValid =
|
|
4449
|
+
this.lastValueValid = value == null || this.dateTimeAdapter.isValid(value);
|
|
4333
4450
|
value = this.getValidDate(value);
|
|
4334
4451
|
const oldDate = this._value;
|
|
4335
4452
|
this._value = value;
|
|
4336
|
-
//
|
|
4453
|
+
// Задаём свойство 'value' поля ввода
|
|
4337
4454
|
this.formatNativeInputValue();
|
|
4338
|
-
//
|
|
4455
|
+
// Проверяем, изменилось ли значение поля ввода
|
|
4339
4456
|
if (!this.dateTimeAdapter.isEqual(oldDate, value)) {
|
|
4340
4457
|
this.valueChange.emit(value);
|
|
4341
4458
|
}
|
|
@@ -4345,21 +4462,15 @@ class OwlDateTimeInputDirective {
|
|
|
4345
4462
|
}
|
|
4346
4463
|
set values(values) {
|
|
4347
4464
|
if (values && values.length > 0) {
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
});
|
|
4352
|
-
this.lastValueValid =
|
|
4353
|
-
(!this._values[0] ||
|
|
4354
|
-
this.dateTimeAdapter.isValid(this._values[0])) &&
|
|
4355
|
-
(!this._values[1] ||
|
|
4356
|
-
this.dateTimeAdapter.isValid(this._values[1]));
|
|
4465
|
+
const deserialized = values.map(v => this.dateTimeAdapter.deserialize(v));
|
|
4466
|
+
this.lastValueValid = deserialized.every(v => v == null || this.dateTimeAdapter.isValid(v));
|
|
4467
|
+
this._values = deserialized.map(v => this.getValidDate(v));
|
|
4357
4468
|
}
|
|
4358
4469
|
else {
|
|
4359
4470
|
this._values = [];
|
|
4360
4471
|
this.lastValueValid = true;
|
|
4361
4472
|
}
|
|
4362
|
-
//
|
|
4473
|
+
// Задаём свойство 'value' поля ввода
|
|
4363
4474
|
this.formatNativeInputValue();
|
|
4364
4475
|
this.valueChange.emit(this._values);
|
|
4365
4476
|
}
|
|
@@ -4378,37 +4489,38 @@ class OwlDateTimeInputDirective {
|
|
|
4378
4489
|
return true;
|
|
4379
4490
|
}
|
|
4380
4491
|
get owlDateTimeInputAriaOwns() {
|
|
4381
|
-
return (this.dtPicker
|
|
4492
|
+
return (this.dtPicker?.opened && this.dtPicker.id) || null;
|
|
4382
4493
|
}
|
|
4383
4494
|
get minIso8601() {
|
|
4384
|
-
return this.min ? this.dateTimeAdapter.toIso8601(this.min) : null;
|
|
4495
|
+
return this.min != null ? this.dateTimeAdapter.toIso8601(this.min) : null;
|
|
4385
4496
|
}
|
|
4386
4497
|
get maxIso8601() {
|
|
4387
|
-
return this.max ? this.dateTimeAdapter.toIso8601(this.max) : null;
|
|
4498
|
+
return this.max != null ? this.dateTimeAdapter.toIso8601(this.max) : null;
|
|
4388
4499
|
}
|
|
4389
4500
|
get owlDateTimeInputDisabled() {
|
|
4390
4501
|
return this.disabled;
|
|
4391
4502
|
}
|
|
4392
|
-
constructor(elmRef, renderer, dateTimeAdapter, dateTimeFormats) {
|
|
4503
|
+
constructor(elmRef, renderer, dateTimeAdapter, dateTimeFormats, changeDetector) {
|
|
4393
4504
|
this.elmRef = elmRef;
|
|
4394
4505
|
this.renderer = renderer;
|
|
4395
4506
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
4396
4507
|
this.dateTimeFormats = dateTimeFormats;
|
|
4508
|
+
this.changeDetector = changeDetector;
|
|
4397
4509
|
/**
|
|
4398
|
-
*
|
|
4510
|
+
* Режим выбора даты
|
|
4399
4511
|
*/
|
|
4400
4512
|
this._selectMode = 'single';
|
|
4401
4513
|
/**
|
|
4402
|
-
*
|
|
4514
|
+
* Символ, разделяющий начало ('from') и конец ('to') диапазона в поле ввода
|
|
4403
4515
|
*/
|
|
4404
4516
|
this.rangeSeparator = '-';
|
|
4405
4517
|
this._values = [];
|
|
4406
4518
|
/**
|
|
4407
|
-
*
|
|
4519
|
+
* Обработчик события `change` этого `<input>`
|
|
4408
4520
|
* */
|
|
4409
4521
|
this.dateTimeChange = new EventEmitter();
|
|
4410
4522
|
/**
|
|
4411
|
-
*
|
|
4523
|
+
* Обработчик события `input` этого `<input>`
|
|
4412
4524
|
* */
|
|
4413
4525
|
this.dateTimeInput = new EventEmitter();
|
|
4414
4526
|
this.dtPickerSub = Subscription.EMPTY;
|
|
@@ -4417,18 +4529,18 @@ class OwlDateTimeInputDirective {
|
|
|
4417
4529
|
this.onModelChange = () => { };
|
|
4418
4530
|
this.onModelTouched = () => { };
|
|
4419
4531
|
this.validatorOnChange = () => { };
|
|
4420
|
-
/**
|
|
4532
|
+
/** Валидатор корректности разбора введённого значения */
|
|
4421
4533
|
this.parseValidator = () => {
|
|
4422
4534
|
return this.lastValueValid
|
|
4423
4535
|
? null
|
|
4424
4536
|
: { owlDateTimeParse: { text: this.elmRef.nativeElement.value } };
|
|
4425
4537
|
};
|
|
4426
|
-
/**
|
|
4538
|
+
/** Валидатор минимальной даты */
|
|
4427
4539
|
this.minValidator = (control) => {
|
|
4428
4540
|
if (this.isInSingleMode) {
|
|
4429
4541
|
const controlValue = this.getValidDate(this.dateTimeAdapter.deserialize(control.value));
|
|
4430
|
-
return
|
|
4431
|
-
|
|
4542
|
+
return this.min == null ||
|
|
4543
|
+
controlValue == null ||
|
|
4432
4544
|
this.dateTimeAdapter.compare(this.min, controlValue) <= 0
|
|
4433
4545
|
? null
|
|
4434
4546
|
: { owlDateTimeMin: { min: this.min, actual: controlValue } };
|
|
@@ -4436,10 +4548,8 @@ class OwlDateTimeInputDirective {
|
|
|
4436
4548
|
else if (this.isInRangeMode && control.value) {
|
|
4437
4549
|
const controlValueFrom = this.getValidDate(this.dateTimeAdapter.deserialize(control.value[0]));
|
|
4438
4550
|
const controlValueTo = this.getValidDate(this.dateTimeAdapter.deserialize(control.value[1]));
|
|
4439
|
-
return
|
|
4440
|
-
|
|
4441
|
-
!controlValueTo ||
|
|
4442
|
-
this.dateTimeAdapter.compare(this.min, controlValueFrom) <= 0
|
|
4551
|
+
return this.min == null ||
|
|
4552
|
+
[controlValueFrom, controlValueTo].every(value => value == null || this.dateTimeAdapter.compare(this.min, value) <= 0)
|
|
4443
4553
|
? null
|
|
4444
4554
|
: {
|
|
4445
4555
|
owlDateTimeMin: {
|
|
@@ -4449,12 +4559,12 @@ class OwlDateTimeInputDirective {
|
|
|
4449
4559
|
};
|
|
4450
4560
|
}
|
|
4451
4561
|
};
|
|
4452
|
-
/**
|
|
4562
|
+
/** Валидатор максимальной даты */
|
|
4453
4563
|
this.maxValidator = (control) => {
|
|
4454
4564
|
if (this.isInSingleMode) {
|
|
4455
4565
|
const controlValue = this.getValidDate(this.dateTimeAdapter.deserialize(control.value));
|
|
4456
|
-
return
|
|
4457
|
-
|
|
4566
|
+
return this.max == null ||
|
|
4567
|
+
controlValue == null ||
|
|
4458
4568
|
this.dateTimeAdapter.compare(this.max, controlValue) >= 0
|
|
4459
4569
|
? null
|
|
4460
4570
|
: { owlDateTimeMax: { max: this.max, actual: controlValue } };
|
|
@@ -4462,10 +4572,8 @@ class OwlDateTimeInputDirective {
|
|
|
4462
4572
|
else if (this.isInRangeMode && control.value) {
|
|
4463
4573
|
const controlValueFrom = this.getValidDate(this.dateTimeAdapter.deserialize(control.value[0]));
|
|
4464
4574
|
const controlValueTo = this.getValidDate(this.dateTimeAdapter.deserialize(control.value[1]));
|
|
4465
|
-
return
|
|
4466
|
-
|
|
4467
|
-
!controlValueTo ||
|
|
4468
|
-
this.dateTimeAdapter.compare(this.max, controlValueTo) >= 0
|
|
4575
|
+
return this.max == null ||
|
|
4576
|
+
[controlValueFrom, controlValueTo].every(value => value == null || this.dateTimeAdapter.compare(this.max, value) >= 0)
|
|
4469
4577
|
? null
|
|
4470
4578
|
: {
|
|
4471
4579
|
owlDateTimeMax: {
|
|
@@ -4475,18 +4583,19 @@ class OwlDateTimeInputDirective {
|
|
|
4475
4583
|
};
|
|
4476
4584
|
}
|
|
4477
4585
|
};
|
|
4478
|
-
/**
|
|
4586
|
+
/** Валидатор соответствия фильтру дат */
|
|
4479
4587
|
this.filterValidator = (control) => {
|
|
4480
|
-
const
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4588
|
+
const values = this.isInRangeMode && Array.isArray(control.value)
|
|
4589
|
+
? control.value
|
|
4590
|
+
: [control.value];
|
|
4591
|
+
return !this._dateTimeFilter || values.every(value => {
|
|
4592
|
+
const date = this.getValidDate(this.dateTimeAdapter.deserialize(value));
|
|
4593
|
+
return date == null || this._dateTimeFilter(date);
|
|
4594
|
+
}) ? null : { owlDateTimeFilter: true };
|
|
4486
4595
|
};
|
|
4487
4596
|
/**
|
|
4488
|
-
*
|
|
4489
|
-
*
|
|
4597
|
+
* Валидатор диапазона дат
|
|
4598
|
+
* Проверяет, что начало диапазона находится не позже конца ('to')
|
|
4490
4599
|
* */
|
|
4491
4600
|
this.rangeValidator = (control) => {
|
|
4492
4601
|
if (this.isInSingleMode || !control.value) {
|
|
@@ -4494,15 +4603,15 @@ class OwlDateTimeInputDirective {
|
|
|
4494
4603
|
}
|
|
4495
4604
|
const controlValueFrom = this.getValidDate(this.dateTimeAdapter.deserialize(control.value[0]));
|
|
4496
4605
|
const controlValueTo = this.getValidDate(this.dateTimeAdapter.deserialize(control.value[1]));
|
|
4497
|
-
return
|
|
4498
|
-
|
|
4606
|
+
return controlValueFrom == null ||
|
|
4607
|
+
controlValueTo == null ||
|
|
4499
4608
|
this.dateTimeAdapter.compare(controlValueFrom, controlValueTo) <= 0
|
|
4500
4609
|
? null
|
|
4501
4610
|
: { owlDateTimeRange: true };
|
|
4502
4611
|
};
|
|
4503
4612
|
/**
|
|
4504
|
-
*
|
|
4505
|
-
*
|
|
4613
|
+
* Валидатор обязательного диапазона дат
|
|
4614
|
+
* Проверяет наличие обеих границ диапазона
|
|
4506
4615
|
* */
|
|
4507
4616
|
this.requiredRangeValidator = (control) => {
|
|
4508
4617
|
if (this.isInSingleMode || !control.value || !this.required) {
|
|
@@ -4510,12 +4619,12 @@ class OwlDateTimeInputDirective {
|
|
|
4510
4619
|
}
|
|
4511
4620
|
const controlValueFrom = this.getValidDate(this.dateTimeAdapter.deserialize(control.value[0]));
|
|
4512
4621
|
const controlValueTo = this.getValidDate(this.dateTimeAdapter.deserialize(control.value[1]));
|
|
4513
|
-
return
|
|
4514
|
-
|
|
4622
|
+
return controlValueFrom == null ||
|
|
4623
|
+
controlValueTo == null
|
|
4515
4624
|
? { owlRequiredDateTimeRange: [controlValueFrom, controlValueTo] }
|
|
4516
4625
|
: null;
|
|
4517
4626
|
};
|
|
4518
|
-
/**
|
|
4627
|
+
/** Объединённый валидатор этого поля ввода */
|
|
4519
4628
|
this.validator = Validators.compose([
|
|
4520
4629
|
this.parseValidator,
|
|
4521
4630
|
this.minValidator,
|
|
@@ -4524,9 +4633,9 @@ class OwlDateTimeInputDirective {
|
|
|
4524
4633
|
this.rangeValidator,
|
|
4525
4634
|
this.requiredRangeValidator
|
|
4526
4635
|
]);
|
|
4527
|
-
/**
|
|
4636
|
+
/** Событие изменения значения пользователем или программно */
|
|
4528
4637
|
this.valueChange = new EventEmitter();
|
|
4529
|
-
/**
|
|
4638
|
+
/** Событие изменения состояния disabled */
|
|
4530
4639
|
this.disabledChange = new EventEmitter();
|
|
4531
4640
|
if (!this.dateTimeAdapter) {
|
|
4532
4641
|
throw Error(`OwlDateTimePicker: No provider found for DateTimeAdapter. You must import ` +
|
|
@@ -4597,7 +4706,7 @@ class OwlDateTimeInputDirective {
|
|
|
4597
4706
|
this.validatorOnChange = fn;
|
|
4598
4707
|
}
|
|
4599
4708
|
/**
|
|
4600
|
-
*
|
|
4709
|
+
* Открывает компонент выбора по сочетанию Alt + ArrowDown
|
|
4601
4710
|
* */
|
|
4602
4711
|
handleKeydownOnHost(event) {
|
|
4603
4712
|
if (event.altKey && event.keyCode === DOWN_ARROW) {
|
|
@@ -4635,11 +4744,11 @@ class OwlDateTimeInputDirective {
|
|
|
4635
4744
|
});
|
|
4636
4745
|
}
|
|
4637
4746
|
/**
|
|
4638
|
-
*
|
|
4747
|
+
* Задаёт свойство 'value' нативного поля ввода
|
|
4639
4748
|
*/
|
|
4640
4749
|
formatNativeInputValue() {
|
|
4641
4750
|
if (this.isInSingleMode) {
|
|
4642
|
-
this.renderer.setProperty(this.elmRef.nativeElement, 'value', this._value
|
|
4751
|
+
this.renderer.setProperty(this.elmRef.nativeElement, 'value', this._value != null
|
|
4643
4752
|
? this.dateTimeAdapter.format(this._value, this.dtPicker.formatString)
|
|
4644
4753
|
: '');
|
|
4645
4754
|
}
|
|
@@ -4647,10 +4756,10 @@ class OwlDateTimeInputDirective {
|
|
|
4647
4756
|
if (this._values && this.values.length > 0) {
|
|
4648
4757
|
const from = this._values[0];
|
|
4649
4758
|
const to = this._values[1];
|
|
4650
|
-
const fromFormatted = from
|
|
4759
|
+
const fromFormatted = from != null
|
|
4651
4760
|
? this.dateTimeAdapter.format(from, this.dtPicker.formatString)
|
|
4652
4761
|
: '';
|
|
4653
|
-
const toFormatted = to
|
|
4762
|
+
const toFormatted = to != null
|
|
4654
4763
|
? this.dateTimeAdapter.format(to, this.dtPicker.formatString)
|
|
4655
4764
|
: '';
|
|
4656
4765
|
if (!fromFormatted && !toFormatted) {
|
|
@@ -4679,7 +4788,7 @@ class OwlDateTimeInputDirective {
|
|
|
4679
4788
|
return;
|
|
4680
4789
|
}
|
|
4681
4790
|
/**
|
|
4682
|
-
*
|
|
4791
|
+
* Регистрирует связь между полем ввода и компонентом выбора
|
|
4683
4792
|
*/
|
|
4684
4793
|
registerDateTimePicker(picker) {
|
|
4685
4794
|
if (picker) {
|
|
@@ -4688,7 +4797,7 @@ class OwlDateTimeInputDirective {
|
|
|
4688
4797
|
}
|
|
4689
4798
|
}
|
|
4690
4799
|
/**
|
|
4691
|
-
*
|
|
4800
|
+
* Преобразует указанный объект в корректный объект даты
|
|
4692
4801
|
*/
|
|
4693
4802
|
getValidDate(obj) {
|
|
4694
4803
|
return this.dateTimeAdapter.isDateInstance(obj) &&
|
|
@@ -4697,14 +4806,14 @@ class OwlDateTimeInputDirective {
|
|
|
4697
4806
|
: null;
|
|
4698
4807
|
}
|
|
4699
4808
|
/**
|
|
4700
|
-
*
|
|
4701
|
-
*
|
|
4702
|
-
*
|
|
4703
|
-
*
|
|
4809
|
+
* Преобразует строку времени в строку даты и времени
|
|
4810
|
+
* При pickerType равном 'timer' поле ввода содержит строку времени
|
|
4811
|
+
* Метод parse адаптера dateTimeAdapter не может разобрать строку времени как объект даты
|
|
4812
|
+
* Поэтому эта функция преобразует строку времени в строку даты и времени
|
|
4704
4813
|
*/
|
|
4705
4814
|
convertTimeStringToDateTimeString(timeString, dateTime) {
|
|
4706
4815
|
if (timeString) {
|
|
4707
|
-
const v = dateTime
|
|
4816
|
+
const v = dateTime ?? this.dateTimeAdapter.now();
|
|
4708
4817
|
const dateString = this.dateTimeAdapter.format(v, this.dateTimeFormats.datePickerInput);
|
|
4709
4818
|
return dateString + ' ' + timeString;
|
|
4710
4819
|
}
|
|
@@ -4713,7 +4822,7 @@ class OwlDateTimeInputDirective {
|
|
|
4713
4822
|
}
|
|
4714
4823
|
}
|
|
4715
4824
|
/**
|
|
4716
|
-
*
|
|
4825
|
+
* Обрабатывает изменение поля ввода в режиме single
|
|
4717
4826
|
*/
|
|
4718
4827
|
changeInputInSingleMode(inputValue) {
|
|
4719
4828
|
let value = inputValue;
|
|
@@ -4721,10 +4830,10 @@ class OwlDateTimeInputDirective {
|
|
|
4721
4830
|
value = this.convertTimeStringToDateTimeString(value, this.value);
|
|
4722
4831
|
}
|
|
4723
4832
|
let result = this.dateTimeAdapter.parse(value, this.dateTimeFormats.parseInput);
|
|
4724
|
-
this.lastValueValid =
|
|
4833
|
+
this.lastValueValid = result == null || this.dateTimeAdapter.isValid(result);
|
|
4725
4834
|
result = this.getValidDate(result);
|
|
4726
|
-
//
|
|
4727
|
-
// result
|
|
4835
|
+
// Если newValue совпадает с oldValue, не отправляем событие valueChange
|
|
4836
|
+
// result равный null означает, что событие ввода произошло, но значение недопустимо
|
|
4728
4837
|
if (!this.isSameValue(result, this._value) || result === null) {
|
|
4729
4838
|
this._value = result;
|
|
4730
4839
|
this.valueChange.emit(result);
|
|
@@ -4737,7 +4846,7 @@ class OwlDateTimeInputDirective {
|
|
|
4737
4846
|
}
|
|
4738
4847
|
}
|
|
4739
4848
|
/**
|
|
4740
|
-
*
|
|
4849
|
+
* Обрабатывает изменение поля ввода в режиме rangeFrom или rangeTo
|
|
4741
4850
|
*/
|
|
4742
4851
|
changeInputInRangeFromToMode(inputValue) {
|
|
4743
4852
|
const originalValue = this._selectMode === 'rangeFrom'
|
|
@@ -4747,9 +4856,9 @@ class OwlDateTimeInputDirective {
|
|
|
4747
4856
|
inputValue = this.convertTimeStringToDateTimeString(inputValue, originalValue);
|
|
4748
4857
|
}
|
|
4749
4858
|
let result = this.dateTimeAdapter.parse(inputValue, this.dateTimeFormats.parseInput);
|
|
4750
|
-
this.lastValueValid =
|
|
4859
|
+
this.lastValueValid = result == null || this.dateTimeAdapter.isValid(result);
|
|
4751
4860
|
result = this.getValidDate(result);
|
|
4752
|
-
//
|
|
4861
|
+
// Если newValue совпадает с oldValue, не отправляем событие valueChange
|
|
4753
4862
|
if ((this._selectMode === 'rangeFrom' &&
|
|
4754
4863
|
this.isSameValue(result, this._values[0]) &&
|
|
4755
4864
|
result) ||
|
|
@@ -4771,10 +4880,11 @@ class OwlDateTimeInputDirective {
|
|
|
4771
4880
|
});
|
|
4772
4881
|
}
|
|
4773
4882
|
/**
|
|
4774
|
-
*
|
|
4883
|
+
* Обрабатывает изменение поля ввода в режиме range
|
|
4775
4884
|
*/
|
|
4776
4885
|
changeInputInRangeMode(inputValue) {
|
|
4777
|
-
const
|
|
4886
|
+
const wasValid = this.lastValueValid;
|
|
4887
|
+
const selecteds = inputValue.split(this.rangeSeparator).map(value => value.trim());
|
|
4778
4888
|
let fromString = selecteds[0];
|
|
4779
4889
|
let toString = selecteds[1];
|
|
4780
4890
|
if (this.dtPicker.pickerType === 'timer') {
|
|
@@ -4784,13 +4894,14 @@ class OwlDateTimeInputDirective {
|
|
|
4784
4894
|
let from = this.dateTimeAdapter.parse(fromString, this.dateTimeFormats.parseInput);
|
|
4785
4895
|
let to = this.dateTimeAdapter.parse(toString, this.dateTimeFormats.parseInput);
|
|
4786
4896
|
this.lastValueValid =
|
|
4787
|
-
(
|
|
4788
|
-
(
|
|
4897
|
+
(from == null || this.dateTimeAdapter.isValid(from)) &&
|
|
4898
|
+
(to == null || this.dateTimeAdapter.isValid(to));
|
|
4789
4899
|
from = this.getValidDate(from);
|
|
4790
4900
|
to = this.getValidDate(to);
|
|
4791
|
-
//
|
|
4901
|
+
// Если newValue совпадает с oldValue, не отправляем событие valueChange
|
|
4792
4902
|
if (!this.isSameValue(from, this._values[0]) ||
|
|
4793
4903
|
!this.isSameValue(to, this._values[1]) ||
|
|
4904
|
+
wasValid !== this.lastValueValid ||
|
|
4794
4905
|
(from === null && to === null)) {
|
|
4795
4906
|
this._values = [from, to];
|
|
4796
4907
|
this.valueChange.emit(this._values);
|
|
@@ -4803,16 +4914,16 @@ class OwlDateTimeInputDirective {
|
|
|
4803
4914
|
}
|
|
4804
4915
|
}
|
|
4805
4916
|
/**
|
|
4806
|
-
*
|
|
4917
|
+
* Проверяет равенство двух значений
|
|
4807
4918
|
*/
|
|
4808
4919
|
isSameValue(first, second) {
|
|
4809
|
-
if (first && second) {
|
|
4920
|
+
if (first != null && second != null) {
|
|
4810
4921
|
return this.dateTimeAdapter.compare(first, second) === 0;
|
|
4811
4922
|
}
|
|
4812
4923
|
return first === second;
|
|
4813
4924
|
}
|
|
4814
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlDateTimeInputDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DateTimeAdapter, optional: true }, { token: OWL_DATE_TIME_FORMATS, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4815
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.0", type: OwlDateTimeInputDirective, isStandalone: false, selector: "input[owlDateTime]", inputs: { required: "required", owlDateTime: "owlDateTime", owlDateTimeFilter: "owlDateTimeFilter",
|
|
4925
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlDateTimeInputDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DateTimeAdapter, optional: true }, { token: OWL_DATE_TIME_FORMATS, optional: true }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4926
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.0", type: OwlDateTimeInputDirective, isStandalone: false, selector: "input[owlDateTime]", inputs: { required: "required", owlDateTime: "owlDateTime", owlDateTimeFilter: "owlDateTimeFilter", disabled: "disabled", min: "min", max: "max", selectMode: "selectMode", rangeSeparator: "rangeSeparator", value: "value", values: "values" }, outputs: { dateTimeChange: "dateTimeChange", dateTimeInput: "dateTimeInput" }, host: { listeners: { "keydown": "handleKeydownOnHost($event)", "blur": "handleBlurOnHost($event)", "input": "handleInputOnHost($event)", "change": "handleChangeOnHost($event)" }, properties: { "attr.aria-haspopup": "owlDateTimeInputAriaHaspopup", "attr.aria-owns": "owlDateTimeInputAriaOwns", "attr.min": "minIso8601", "attr.max": "maxIso8601", "disabled": "owlDateTimeInputDisabled" } }, providers: [
|
|
4816
4927
|
OWL_DATETIME_VALUE_ACCESSOR$1,
|
|
4817
4928
|
OWL_DATETIME_VALIDATORS,
|
|
4818
4929
|
], exportAs: ["owlDateTimeInput"], ngImport: i0 }); }
|
|
@@ -4846,13 +4957,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4846
4957
|
}, {
|
|
4847
4958
|
type: Inject,
|
|
4848
4959
|
args: [OWL_DATE_TIME_FORMATS]
|
|
4849
|
-
}] }], propDecorators: { required: [{
|
|
4960
|
+
}] }, { type: i0.ChangeDetectorRef }], propDecorators: { required: [{
|
|
4850
4961
|
type: Input
|
|
4851
4962
|
}], owlDateTime: [{
|
|
4852
4963
|
type: Input
|
|
4853
4964
|
}], owlDateTimeFilter: [{
|
|
4854
4965
|
type: Input
|
|
4855
|
-
}],
|
|
4966
|
+
}], disabled: [{
|
|
4856
4967
|
type: Input
|
|
4857
4968
|
}], min: [{
|
|
4858
4969
|
type: Input
|
|
@@ -4921,6 +5032,8 @@ class OwlDateTimeInlineComponent extends OwlDateTime {
|
|
|
4921
5032
|
}
|
|
4922
5033
|
set disabled(value) {
|
|
4923
5034
|
this._disabled = coerceBooleanProperty(value);
|
|
5035
|
+
this.changeDetector.markForCheck();
|
|
5036
|
+
this.container?.refreshView();
|
|
4924
5037
|
}
|
|
4925
5038
|
get selectMode() {
|
|
4926
5039
|
return this._selectMode;
|
|
@@ -4935,18 +5048,18 @@ class OwlDateTimeInlineComponent extends OwlDateTime {
|
|
|
4935
5048
|
this._selectMode = mode;
|
|
4936
5049
|
}
|
|
4937
5050
|
get startAt() {
|
|
4938
|
-
if (this._startAt) {
|
|
5051
|
+
if (this._startAt != null) {
|
|
4939
5052
|
return this._startAt;
|
|
4940
5053
|
}
|
|
4941
5054
|
if (this.selectMode === 'single') {
|
|
4942
|
-
return this.value
|
|
5055
|
+
return this.value ?? null;
|
|
4943
5056
|
}
|
|
4944
5057
|
else if (this.selectMode === 'range' ||
|
|
4945
5058
|
this.selectMode === 'rangeFrom') {
|
|
4946
|
-
return this.values[0]
|
|
5059
|
+
return this.values[0] ?? null;
|
|
4947
5060
|
}
|
|
4948
5061
|
else if (this.selectMode === 'rangeTo') {
|
|
4949
|
-
return this.values[1]
|
|
5062
|
+
return this.values[1] ?? null;
|
|
4950
5063
|
}
|
|
4951
5064
|
else {
|
|
4952
5065
|
return null;
|
|
@@ -4956,15 +5069,15 @@ class OwlDateTimeInlineComponent extends OwlDateTime {
|
|
|
4956
5069
|
this._startAt = this.getValidDate(this.dateTimeAdapter.deserialize(date));
|
|
4957
5070
|
}
|
|
4958
5071
|
get endAt() {
|
|
4959
|
-
if (this._endAt) {
|
|
5072
|
+
if (this._endAt != null) {
|
|
4960
5073
|
return this._endAt;
|
|
4961
5074
|
}
|
|
4962
5075
|
if (this.selectMode === 'single') {
|
|
4963
|
-
return this.value
|
|
5076
|
+
return this.value ?? null;
|
|
4964
5077
|
}
|
|
4965
5078
|
else if (this.selectMode === 'range' ||
|
|
4966
5079
|
this.selectMode === 'rangeFrom') {
|
|
4967
|
-
return this.values[1]
|
|
5080
|
+
return this.values[1] ?? null;
|
|
4968
5081
|
}
|
|
4969
5082
|
else {
|
|
4970
5083
|
return null;
|
|
@@ -4980,14 +5093,14 @@ class OwlDateTimeInlineComponent extends OwlDateTime {
|
|
|
4980
5093
|
this._dateTimeFilter = filter;
|
|
4981
5094
|
}
|
|
4982
5095
|
get minDateTime() {
|
|
4983
|
-
return this._min
|
|
5096
|
+
return this._min ?? null;
|
|
4984
5097
|
}
|
|
4985
5098
|
set minDateTime(value) {
|
|
4986
5099
|
this._min = this.getValidDate(this.dateTimeAdapter.deserialize(value));
|
|
4987
5100
|
this.changeDetector.markForCheck();
|
|
4988
5101
|
}
|
|
4989
5102
|
get maxDateTime() {
|
|
4990
|
-
return this._max
|
|
5103
|
+
return this._max ?? null;
|
|
4991
5104
|
}
|
|
4992
5105
|
set maxDateTime(value) {
|
|
4993
5106
|
this._max = this.getValidDate(this.dateTimeAdapter.deserialize(value));
|
|
@@ -5010,7 +5123,7 @@ class OwlDateTimeInlineComponent extends OwlDateTime {
|
|
|
5010
5123
|
values = values.map(v => {
|
|
5011
5124
|
v = this.dateTimeAdapter.deserialize(v);
|
|
5012
5125
|
v = this.getValidDate(v);
|
|
5013
|
-
return v ? this.dateTimeAdapter.clone(v) : null;
|
|
5126
|
+
return v != null ? this.dateTimeAdapter.clone(v) : null;
|
|
5014
5127
|
});
|
|
5015
5128
|
this._values = [...values];
|
|
5016
5129
|
this.selecteds = [...values];
|
|
@@ -5057,27 +5170,27 @@ class OwlDateTimeInlineComponent extends OwlDateTime {
|
|
|
5057
5170
|
this.dateTimeAdapter = dateTimeAdapter;
|
|
5058
5171
|
this.dateTimeFormats = dateTimeFormats;
|
|
5059
5172
|
/**
|
|
5060
|
-
*
|
|
5061
|
-
* 'both'
|
|
5062
|
-
* 'calendar'
|
|
5063
|
-
* 'timer'
|
|
5173
|
+
* Задаёт тип компонента выбора даты и времени:
|
|
5174
|
+
* 'both' — календарь и выбор времени
|
|
5175
|
+
* 'calendar' — только календарь
|
|
5176
|
+
* 'timer' — только выбор времени
|
|
5064
5177
|
*/
|
|
5065
5178
|
this._pickerType = 'both';
|
|
5066
5179
|
this._disabled = false;
|
|
5067
5180
|
this._selectMode = 'single';
|
|
5068
5181
|
this._values = [];
|
|
5069
5182
|
/**
|
|
5070
|
-
*
|
|
5071
|
-
*
|
|
5183
|
+
* Передаёт выбранный год в представлении нескольких лет
|
|
5184
|
+
* При этом выбранная дата не изменяется
|
|
5072
5185
|
* */
|
|
5073
5186
|
this.yearSelected = new EventEmitter();
|
|
5074
5187
|
/**
|
|
5075
|
-
*
|
|
5076
|
-
*
|
|
5188
|
+
* Передаёт выбранный месяц в представлении года
|
|
5189
|
+
* При этом выбранная дата не изменяется
|
|
5077
5190
|
* */
|
|
5078
5191
|
this.monthSelected = new EventEmitter();
|
|
5079
5192
|
/**
|
|
5080
|
-
*
|
|
5193
|
+
* Передаёт выбранную дату
|
|
5081
5194
|
* */
|
|
5082
5195
|
this.dateSelected = new EventEmitter();
|
|
5083
5196
|
this._selecteds = [];
|
|
@@ -5120,30 +5233,31 @@ class OwlDateTimeInlineComponent extends OwlDateTime {
|
|
|
5120
5233
|
this.onModelTouched();
|
|
5121
5234
|
}
|
|
5122
5235
|
/**
|
|
5123
|
-
*
|
|
5236
|
+
* Передаёт выбранный год в представлении нескольких лет
|
|
5124
5237
|
* */
|
|
5125
5238
|
selectYear(normalizedYear) {
|
|
5126
5239
|
this.yearSelected.emit(normalizedYear);
|
|
5127
5240
|
}
|
|
5128
5241
|
/**
|
|
5129
|
-
*
|
|
5242
|
+
* Передаёт выбранный месяц в представлении года
|
|
5130
5243
|
* */
|
|
5131
5244
|
selectMonth(normalizedMonth) {
|
|
5132
5245
|
this.monthSelected.emit(normalizedMonth);
|
|
5133
5246
|
}
|
|
5134
5247
|
/**
|
|
5135
|
-
*
|
|
5248
|
+
* Передаёт выбранную дату
|
|
5136
5249
|
* */
|
|
5137
5250
|
selectDate(normalizedDate) {
|
|
5138
5251
|
this.dateSelected.emit(normalizedDate);
|
|
5139
5252
|
}
|
|
5140
5253
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlDateTimeInlineComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: DateTimeAdapter, optional: true }, { token: OWL_DATE_TIME_FORMATS, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5141
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: OwlDateTimeInlineComponent, isStandalone: false, selector: "owl-date-time-inline", inputs: { pickerType: "pickerType", disabled: "disabled", selectMode: "selectMode", startAt: "startAt", endAt: "endAt", dateTimeFilter: ["owlDateTimeFilter", "dateTimeFilter"], minDateTime: ["min", "minDateTime"], maxDateTime: ["max", "maxDateTime"], value: "value", values: "values" }, outputs: { yearSelected: "yearSelected", monthSelected: "monthSelected", dateSelected: "dateSelected" }, host: { properties: { "class.owl-dt-inline": "owlDTInlineClass" } }, providers: [OWL_DATETIME_VALUE_ACCESSOR], viewQueries: [{ propertyName: "container", first: true, predicate: OwlDateTimeContainerComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<owl-date-time-container></owl-date-time-container>", styles: [":host{--container-enter-animation-duration: 0;--container-leave-animation-duration: 0}\n"], dependencies: [{ kind: "component", type: OwlDateTimeContainerComponent, selector: "owl-date-time-container", exportAs: ["owlDateTimeContainer"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5254
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.0", type: OwlDateTimeInlineComponent, isStandalone: false, selector: "owl-date-time-inline", inputs: { pickerType: "pickerType", disabled: "disabled", selectMode: "selectMode", startAt: "startAt", endAt: "endAt", dateTimeFilter: ["owlDateTimeFilter", "dateTimeFilter"], minDateTime: ["min", "minDateTime"], maxDateTime: ["max", "maxDateTime"], value: "value", values: "values" }, outputs: { yearSelected: "yearSelected", monthSelected: "monthSelected", dateSelected: "dateSelected" }, host: { properties: { "class.owl-dt-inline": "owlDTInlineClass", "attr.aria-disabled": "disabled || null" } }, providers: [OWL_DATETIME_VALUE_ACCESSOR], viewQueries: [{ propertyName: "container", first: true, predicate: OwlDateTimeContainerComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<owl-date-time-container></owl-date-time-container>", styles: [":host{--container-enter-animation-duration: 0;--container-leave-animation-duration: 0}\n"], dependencies: [{ kind: "component", type: OwlDateTimeContainerComponent, selector: "owl-date-time-container", exportAs: ["owlDateTimeContainer"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5142
5255
|
}
|
|
5143
5256
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: OwlDateTimeInlineComponent, decorators: [{
|
|
5144
5257
|
type: Component,
|
|
5145
5258
|
args: [{ selector: 'owl-date-time-inline', host: {
|
|
5146
|
-
'[class.owl-dt-inline]': 'owlDTInlineClass'
|
|
5259
|
+
'[class.owl-dt-inline]': 'owlDTInlineClass',
|
|
5260
|
+
'[attr.aria-disabled]': 'disabled || null'
|
|
5147
5261
|
}, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, providers: [OWL_DATETIME_VALUE_ACCESSOR], template: "<owl-date-time-container></owl-date-time-container>", styles: [":host{--container-enter-animation-duration: 0;--container-leave-animation-duration: 0}\n"] }]
|
|
5148
5262
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: DateTimeAdapter, decorators: [{
|
|
5149
5263
|
type: Optional
|
|
@@ -5291,10 +5405,10 @@ class LuxonDateTimeAdapter extends DateTimeAdapter {
|
|
|
5291
5405
|
this.owlDateTimeLocale = owlDateTimeLocale;
|
|
5292
5406
|
this.firstMonthOfTheYear = 0;
|
|
5293
5407
|
/**
|
|
5294
|
-
* 0 -
|
|
5295
|
-
* 1 -
|
|
5408
|
+
* 0 - воскресенье
|
|
5409
|
+
* 1 - понедельник
|
|
5296
5410
|
* ...
|
|
5297
|
-
* 6 -
|
|
5411
|
+
* 6 - суббота
|
|
5298
5412
|
*/
|
|
5299
5413
|
this.firstDayOfTheWeek = 0;
|
|
5300
5414
|
this.setLocale(owlDateTimeLocale || Settings.defaultLocale || 'ru');
|
|
@@ -5303,25 +5417,25 @@ class LuxonDateTimeAdapter extends DateTimeAdapter {
|
|
|
5303
5417
|
return date.year;
|
|
5304
5418
|
}
|
|
5305
5419
|
/**
|
|
5306
|
-
*
|
|
5307
|
-
* 0 -
|
|
5308
|
-
* 11 -
|
|
5420
|
+
* Компонент выбора даты ожидает индекс месяца:
|
|
5421
|
+
* 0 - январь
|
|
5422
|
+
* 11 - декабрь
|
|
5309
5423
|
*
|
|
5310
|
-
* Luxon
|
|
5311
|
-
* 1 -
|
|
5312
|
-
* 12 -
|
|
5424
|
+
* Luxon использует:
|
|
5425
|
+
* 1 - январь
|
|
5426
|
+
* 12 - декабрь
|
|
5313
5427
|
*/
|
|
5314
5428
|
getMonth(date) {
|
|
5315
5429
|
return date.month - 1;
|
|
5316
5430
|
}
|
|
5317
5431
|
/**
|
|
5318
|
-
*
|
|
5319
|
-
* 0 -
|
|
5320
|
-
* 6 -
|
|
5432
|
+
* Компонент выбора даты ожидает:
|
|
5433
|
+
* 0 - воскресенье
|
|
5434
|
+
* 6 - суббота
|
|
5321
5435
|
*
|
|
5322
|
-
* Luxon
|
|
5323
|
-
* 1 -
|
|
5324
|
-
* 7 -
|
|
5436
|
+
* День недели в Luxon:
|
|
5437
|
+
* 1 - понедельник
|
|
5438
|
+
* 7 - воскресенье
|
|
5325
5439
|
*/
|
|
5326
5440
|
getDay(date) {
|
|
5327
5441
|
return date.weekday % 7;
|
|
@@ -5346,9 +5460,9 @@ class LuxonDateTimeAdapter extends DateTimeAdapter {
|
|
|
5346
5460
|
}
|
|
5347
5461
|
differenceInCalendarDays(dateLeft, dateRight) {
|
|
5348
5462
|
if (this.isValid(dateLeft) && this.isValid(dateRight)) {
|
|
5349
|
-
return Math.round(dateLeft.
|
|
5463
|
+
return Math.round(DateTime.utc(dateLeft.year, dateLeft.month, dateLeft.day).diff(DateTime.utc(dateRight.year, dateRight.month, dateRight.day), 'days').days);
|
|
5350
5464
|
}
|
|
5351
|
-
return
|
|
5465
|
+
return Number.NaN;
|
|
5352
5466
|
}
|
|
5353
5467
|
getYearName(date) {
|
|
5354
5468
|
return date.setLocale(this.locale).toFormat('yyyy');
|
|
@@ -5358,8 +5472,8 @@ class LuxonDateTimeAdapter extends DateTimeAdapter {
|
|
|
5358
5472
|
}
|
|
5359
5473
|
getDayOfWeekNames(style) {
|
|
5360
5474
|
const weekdays = Info.weekdays(style, { locale: this.locale });
|
|
5361
|
-
// Luxon
|
|
5362
|
-
//
|
|
5475
|
+
// Luxon возвращает дни недели от понедельника до воскресенья
|
|
5476
|
+
// Компонент выбора даты ожидает порядок от воскресенья до субботы
|
|
5363
5477
|
return [
|
|
5364
5478
|
weekdays[6],
|
|
5365
5479
|
...weekdays.slice(0, 6),
|
|
@@ -5413,6 +5527,9 @@ class LuxonDateTimeAdapter extends DateTimeAdapter {
|
|
|
5413
5527
|
return date.set({ second: amount });
|
|
5414
5528
|
}
|
|
5415
5529
|
createDate(year, month, date, hours = 0, minutes = 0, seconds = 0) {
|
|
5530
|
+
if (hours < 0 || hours > 23) {
|
|
5531
|
+
throw Error(`LuxonDateTimeAdapter: Invalid hours "${hours}". Hours must be between 0 and 23.`);
|
|
5532
|
+
}
|
|
5416
5533
|
const result = DateTime.local(year, month + 1, date, hours, minutes, seconds, 0).setLocale(this.locale);
|
|
5417
5534
|
if (!result.isValid) {
|
|
5418
5535
|
throw Error(`LuxonDateTimeAdapter: Invalid date "${date}" for month with index "${month}".`);
|
|
@@ -5452,7 +5569,7 @@ class LuxonDateTimeAdapter extends DateTimeAdapter {
|
|
|
5452
5569
|
if (typeof value !== 'string') {
|
|
5453
5570
|
return this.invalid();
|
|
5454
5571
|
}
|
|
5455
|
-
const formats = Array.isArray(parseFormat) ? parseFormat : [parseFormat];
|
|
5572
|
+
const formats = Array.isArray(parseFormat) ? parseFormat : parseFormat ? [parseFormat] : [];
|
|
5456
5573
|
for (const format of formats) {
|
|
5457
5574
|
const parsed = DateTime.fromFormat(value, format, {
|
|
5458
5575
|
locale: this.locale,
|
|
@@ -5570,11 +5687,11 @@ class UnixTimestampDateTimeAdapter extends DateTimeAdapter {
|
|
|
5570
5687
|
this.owlDateTimeLocale = owlDateTimeLocale;
|
|
5571
5688
|
this.firstMonthOfTheYear = 0;
|
|
5572
5689
|
/**
|
|
5573
|
-
*
|
|
5574
|
-
* 0 -
|
|
5575
|
-
* 1 -
|
|
5690
|
+
* Компонент выбора даты ожидает:
|
|
5691
|
+
* 0 - воскресенье
|
|
5692
|
+
* 1 - понедельник
|
|
5576
5693
|
* ...
|
|
5577
|
-
* 6 -
|
|
5694
|
+
* 6 - суббота
|
|
5578
5695
|
*/
|
|
5579
5696
|
this.firstDayOfTheWeek = 0;
|
|
5580
5697
|
this.setLocale(owlDateTimeLocale || Settings.defaultLocale || 'ru');
|
|
@@ -5583,25 +5700,25 @@ class UnixTimestampDateTimeAdapter extends DateTimeAdapter {
|
|
|
5583
5700
|
return this.fromTimestamp(date).year;
|
|
5584
5701
|
}
|
|
5585
5702
|
/**
|
|
5586
|
-
*
|
|
5587
|
-
* 0 -
|
|
5588
|
-
* 11 -
|
|
5703
|
+
* Компонент выбора даты ожидает:
|
|
5704
|
+
* 0 - январь
|
|
5705
|
+
* 11 - декабрь
|
|
5589
5706
|
*
|
|
5590
|
-
* Luxon
|
|
5591
|
-
* 1 -
|
|
5592
|
-
* 12 -
|
|
5707
|
+
* Luxon использует:
|
|
5708
|
+
* 1 - январь
|
|
5709
|
+
* 12 - декабрь
|
|
5593
5710
|
*/
|
|
5594
5711
|
getMonth(date) {
|
|
5595
5712
|
return this.fromTimestamp(date).month - 1;
|
|
5596
5713
|
}
|
|
5597
5714
|
/**
|
|
5598
|
-
*
|
|
5599
|
-
* 0 -
|
|
5600
|
-
* 6 -
|
|
5715
|
+
* Компонент выбора даты ожидает:
|
|
5716
|
+
* 0 - воскресенье
|
|
5717
|
+
* 6 - суббота
|
|
5601
5718
|
*
|
|
5602
|
-
* Luxon
|
|
5603
|
-
* 1 -
|
|
5604
|
-
* 7 -
|
|
5719
|
+
* День недели в Luxon:
|
|
5720
|
+
* 1 - понедельник
|
|
5721
|
+
* 7 - воскресенье
|
|
5605
5722
|
*/
|
|
5606
5723
|
getDay(date) {
|
|
5607
5724
|
return this.fromTimestamp(date).weekday % 7;
|
|
@@ -5640,8 +5757,8 @@ class UnixTimestampDateTimeAdapter extends DateTimeAdapter {
|
|
|
5640
5757
|
}
|
|
5641
5758
|
getDayOfWeekNames(style) {
|
|
5642
5759
|
const weekdays = Info.weekdays(style, { locale: this.locale });
|
|
5643
|
-
// Luxon
|
|
5644
|
-
//
|
|
5760
|
+
// Luxon возвращает дни недели от понедельника до воскресенья
|
|
5761
|
+
// Компонент выбора даты ожидает порядок от воскресенья до субботы
|
|
5645
5762
|
return [
|
|
5646
5763
|
weekdays[6],
|
|
5647
5764
|
...weekdays.slice(0, 6),
|
|
@@ -5666,7 +5783,7 @@ class UnixTimestampDateTimeAdapter extends DateTimeAdapter {
|
|
|
5666
5783
|
return this.fromTimestamp(dateLeft).hasSame(this.fromTimestamp(dateRight), 'day');
|
|
5667
5784
|
}
|
|
5668
5785
|
isValid(date) {
|
|
5669
|
-
return typeof date === 'number' &&
|
|
5786
|
+
return typeof date === 'number' && Number.isFinite(date) && this.fromTimestamp(date).isValid;
|
|
5670
5787
|
}
|
|
5671
5788
|
invalid() {
|
|
5672
5789
|
return NaN;
|
|
@@ -5705,6 +5822,9 @@ class UnixTimestampDateTimeAdapter extends DateTimeAdapter {
|
|
|
5705
5822
|
.toMillis();
|
|
5706
5823
|
}
|
|
5707
5824
|
createDate(year, month, date, hours = 0, minutes = 0, seconds = 0) {
|
|
5825
|
+
if (hours < 0 || hours > 23) {
|
|
5826
|
+
throw Error(`UnixTimestampDateTimeAdapter: Invalid hours "${hours}". Hours must be between 0 and 23.`);
|
|
5827
|
+
}
|
|
5708
5828
|
const result = DateTime.local(year, month + 1, date, hours, minutes, seconds, 0).setLocale(this.locale);
|
|
5709
5829
|
if (!result.isValid) {
|
|
5710
5830
|
throw Error(`UnixTimestampDateTimeAdapter: Invalid date "${date}" for month with index "${month}".`);
|
|
@@ -5720,9 +5840,9 @@ class UnixTimestampDateTimeAdapter extends DateTimeAdapter {
|
|
|
5720
5840
|
.toMillis();
|
|
5721
5841
|
}
|
|
5722
5842
|
/**
|
|
5723
|
-
*
|
|
5724
|
-
* - string => Luxon
|
|
5725
|
-
* - Intl.DateTimeFormatOptions =>
|
|
5843
|
+
* Форматирование с поддержкой двух видов формата:
|
|
5844
|
+
* - string => формат Luxon, например 'dd.MM.yyyy HH:mm'
|
|
5845
|
+
* - Intl.DateTimeFormatOptions => форматирование, совместимое с прежним адаптером
|
|
5726
5846
|
*/
|
|
5727
5847
|
format(date, displayFormat) {
|
|
5728
5848
|
if (!this.isValid(date)) {
|