@natec/mef-dev-ui-kit 16.2.1 → 16.2.2
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.
- package/esm2022/lib/markup-kit/utils/datepicker/datepicker/datepicker.component.mjs +591 -0
- package/esm2022/lib/markup-kit/utils/datepicker/datepicker.module.mjs +21 -0
- package/esm2022/lib/markup-kit/utils/datepicker/index.mjs +3 -0
- package/esm2022/lib/pg-components/select/select.component.mjs +3 -3
- package/esm2022/public-api.mjs +2 -1
- package/fesm2022/natec-mef-dev-ui-kit.mjs +2192 -1592
- package/fesm2022/natec-mef-dev-ui-kit.mjs.map +1 -1
- package/lib/markup-kit/utils/datepicker/datepicker/datepicker.component.d.ts +421 -0
- package/lib/markup-kit/utils/datepicker/datepicker.module.d.ts +10 -0
- package/lib/markup-kit/utils/datepicker/index.d.ts +2 -0
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
import { Component, HostListener, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
import * as i1 from "@angular/common";
|
|
4
|
+
import * as i2 from "@angular/forms";
|
|
5
|
+
import * as i3 from "../../../../pg-components/select/option.component";
|
|
6
|
+
import * as i4 from "../../../../pg-components/select/select.component";
|
|
7
|
+
/**
|
|
8
|
+
* Datepicker Component for selecting dates.
|
|
9
|
+
*
|
|
10
|
+
* This component allows users to pick a date from a calendar interface.
|
|
11
|
+
* It supports various configuration options such as language, date format, and date range.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* <mefdev-datepicker
|
|
15
|
+
* [lang]="'uk'"
|
|
16
|
+
* [dateFormat]="'dd/MM/yyyy'"
|
|
17
|
+
* [range]="{startYear: 1900, toYear: 300}"
|
|
18
|
+
* [disabled]="false"
|
|
19
|
+
* (dateChanged)="onDateChanged($event)"
|
|
20
|
+
* [topOffset]="'20'"
|
|
21
|
+
* [leftOffset]="'10'">
|
|
22
|
+
* </mefdev-datepicker>
|
|
23
|
+
*
|
|
24
|
+
* <example-url>https://mef.dev/ui_kit_demo/view/utils/datepicker</example-url>
|
|
25
|
+
*/
|
|
26
|
+
export class DatepickerComponent {
|
|
27
|
+
datePipe;
|
|
28
|
+
elementRef;
|
|
29
|
+
/**
|
|
30
|
+
* Flag to determine if the calendar is open or closed.
|
|
31
|
+
* Default value: false (closed).
|
|
32
|
+
*/
|
|
33
|
+
isCalendarOpen = false;
|
|
34
|
+
/**
|
|
35
|
+
* Flag to determine if the component is in editing mode.
|
|
36
|
+
* Default value: false (not in editing mode).
|
|
37
|
+
*/
|
|
38
|
+
isEditing = false;
|
|
39
|
+
/**
|
|
40
|
+
* The currently selected date.
|
|
41
|
+
* Default value: Today's date.
|
|
42
|
+
*/
|
|
43
|
+
selectedDate = new Date();
|
|
44
|
+
/**
|
|
45
|
+
* The formatted date for display in the input.
|
|
46
|
+
* Default value: Formatted representation of the selected date.
|
|
47
|
+
*/
|
|
48
|
+
formattedDate;
|
|
49
|
+
/**
|
|
50
|
+
* Track the edited date separately when in editing mode.
|
|
51
|
+
* Default value: An empty string.
|
|
52
|
+
*/
|
|
53
|
+
editedDate = '';
|
|
54
|
+
/**
|
|
55
|
+
* Flag to determine if the month dropdown is open or closed.
|
|
56
|
+
* Default value: true (open).
|
|
57
|
+
*/
|
|
58
|
+
isMonthDropdownOpen = true;
|
|
59
|
+
/**
|
|
60
|
+
* Flag to determine if the year dropdown is open or closed.
|
|
61
|
+
* Default value: true (open).
|
|
62
|
+
*/
|
|
63
|
+
isYearDropdownOpen = true;
|
|
64
|
+
/**
|
|
65
|
+
* The selected month (0-11).
|
|
66
|
+
* Default value: The month of the selected date.
|
|
67
|
+
*/
|
|
68
|
+
selectedDateMonth = this.selectedDate.getMonth();
|
|
69
|
+
/**
|
|
70
|
+
* The selected year.
|
|
71
|
+
* Default value: The year of the selected date.
|
|
72
|
+
*/
|
|
73
|
+
selectedDateYear = this.selectedDate.getFullYear();
|
|
74
|
+
/**
|
|
75
|
+
* An array of years for the year dropdown.
|
|
76
|
+
* Default value: An array of years within the specified range.
|
|
77
|
+
*/
|
|
78
|
+
years;
|
|
79
|
+
/**
|
|
80
|
+
* The language/locale for the datepicker.
|
|
81
|
+
* Default value: 'en' (English).
|
|
82
|
+
* @example
|
|
83
|
+
* <mefdev-datepicker
|
|
84
|
+
* [lang] = "'uk'">
|
|
85
|
+
* </mefdev-datepicker>
|
|
86
|
+
*/
|
|
87
|
+
lang = 'en';
|
|
88
|
+
/**
|
|
89
|
+
* The date format for displaying the selected date.
|
|
90
|
+
* Default value: 'EEE MMM dd yyyy'.
|
|
91
|
+
* @example
|
|
92
|
+
* <mefdev-datepicker
|
|
93
|
+
* [dateFormat]="'dd/MM/yyyy'">
|
|
94
|
+
* </mefdev-datepicker>
|
|
95
|
+
*/
|
|
96
|
+
dateFormat = 'EEE MMM dd yyyy';
|
|
97
|
+
/**
|
|
98
|
+
* The range of years available in the year dropdown.
|
|
99
|
+
* Default value: { startYear: 1900, toYear: 300 }.
|
|
100
|
+
* @example
|
|
101
|
+
* <mefdev-datepicker
|
|
102
|
+
* [range]="{startYear: 1900, toYear: 300}">
|
|
103
|
+
* </mefdev-datepicker>
|
|
104
|
+
*/
|
|
105
|
+
yearsRange = { startYear: 1900, toYear: 300 };
|
|
106
|
+
/**
|
|
107
|
+
* Whether the datepicker is disabled or not.
|
|
108
|
+
* Default value: false (enabled).
|
|
109
|
+
* @example
|
|
110
|
+
* <mefdev-datepicker
|
|
111
|
+
* [disabled]="false">
|
|
112
|
+
* </mefdev-datepicker>
|
|
113
|
+
*/
|
|
114
|
+
disabled = false;
|
|
115
|
+
/**
|
|
116
|
+
* The top offset for positioning the datepicker.
|
|
117
|
+
* Default value: '20'.
|
|
118
|
+
* @example
|
|
119
|
+
* <mefdev-datepicker
|
|
120
|
+
* [topOffset]="'20'">
|
|
121
|
+
* </mefdev-datepicker>
|
|
122
|
+
*/
|
|
123
|
+
topOffset = '20';
|
|
124
|
+
/**
|
|
125
|
+
* The left offset for positioning the datepicker.
|
|
126
|
+
* Default value: '10'.
|
|
127
|
+
* @example
|
|
128
|
+
* <mefdev-datepicker
|
|
129
|
+
* [leftOffset]="'10'">
|
|
130
|
+
* </mefdev-datepicker>
|
|
131
|
+
*/
|
|
132
|
+
leftOffset = '10'; //Default value
|
|
133
|
+
/**
|
|
134
|
+
* Event emitted when the selected date in the datepicker changes.
|
|
135
|
+
* It emits a `Date` object representing the selected date.
|
|
136
|
+
* @example
|
|
137
|
+
* <mefdev-datepicker
|
|
138
|
+
* (dateChanged)="onDateChanged($event)">
|
|
139
|
+
* </mefdev-datepicker>
|
|
140
|
+
*/
|
|
141
|
+
dateChanged = new EventEmitter();
|
|
142
|
+
/**
|
|
143
|
+
* Regular expression to validate user input for date in the format "dd/MM/yyyy".
|
|
144
|
+
* - The day (dd) should be between 01 and 31.
|
|
145
|
+
* - The month (MM) should be between 01 and 12.
|
|
146
|
+
* - The year (yyyy) should be a 4-digit number.
|
|
147
|
+
*/
|
|
148
|
+
dateRegExp = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/;
|
|
149
|
+
/**
|
|
150
|
+
* The string entered by the user for date input.
|
|
151
|
+
* This variable stores the user's input as they type in the date field.
|
|
152
|
+
*/
|
|
153
|
+
userInput = '';
|
|
154
|
+
/**
|
|
155
|
+
* Host listener for document click events to handle calendar interaction.
|
|
156
|
+
* This function checks if a click event occurred within the calendar or input elements.
|
|
157
|
+
* - If the click occurred within the calendar, no action is taken.
|
|
158
|
+
* - If the click occurred within the input element and the component is not in editing mode,
|
|
159
|
+
* it opens the calendar.
|
|
160
|
+
* - If the click occurred outside the calendar and input, it closes the calendar.
|
|
161
|
+
* @param event The MouseEvent object representing the click event.
|
|
162
|
+
*/
|
|
163
|
+
onClick(event) {
|
|
164
|
+
const targetElement = event.target;
|
|
165
|
+
const calendarElement = this.elementRef.nativeElement.querySelector('.calendar');
|
|
166
|
+
const inputElement = this.elementRef.nativeElement.querySelector('input');
|
|
167
|
+
if (calendarElement && calendarElement.contains(targetElement)) {
|
|
168
|
+
// Клік відбувся на елементі календаря, нічого не робимо
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (inputElement && inputElement.contains(targetElement) && !this.isEditing) {
|
|
172
|
+
// Клік відбувся на елементі input, відкриваємо календар
|
|
173
|
+
this.isCalendarOpen = true;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Клік відбувся поза календарем та input, закриваємо календар
|
|
177
|
+
this.isCalendarOpen = false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Constructor for the DatepickerComponent class.
|
|
182
|
+
* @param datePipe A service for formatting and parsing dates.
|
|
183
|
+
* @param elementRef A reference to the element on which this component is attached.
|
|
184
|
+
* It is used to access DOM elements.
|
|
185
|
+
*/
|
|
186
|
+
constructor(datePipe, elementRef) {
|
|
187
|
+
this.datePipe = datePipe;
|
|
188
|
+
this.elementRef = elementRef;
|
|
189
|
+
this.updateInputValue();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Lifecycle hook called after the component is initialized.
|
|
193
|
+
* It initializes the years for the year select dropdown.
|
|
194
|
+
*/
|
|
195
|
+
ngOnInit() {
|
|
196
|
+
this.initializeYears();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Lifecycle hook called whenever the input properties of the component change.
|
|
200
|
+
* It updates the input value.
|
|
201
|
+
*/
|
|
202
|
+
ngOnChanges() {
|
|
203
|
+
this.updateInputValue();
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* An array of month names based on the selected language.
|
|
207
|
+
* It provides localized month names for display in the datepicker.
|
|
208
|
+
*/
|
|
209
|
+
get months() {
|
|
210
|
+
return this.getMonthList(this.lang);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* An array of weekday names based on the selected language.
|
|
214
|
+
* It provides localized weekday names for display in the datepicker.
|
|
215
|
+
*/
|
|
216
|
+
get weekdays() {
|
|
217
|
+
return this.getWeekdayList(this.lang);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Initialize the list of years to be displayed in the year dropdown.
|
|
221
|
+
* This method populates the 'years' array with a range of years based on the provided 'yearsRange' configuration.
|
|
222
|
+
* @example
|
|
223
|
+
* ```
|
|
224
|
+
* // Assuming 'yearsRange' is { startYear: 1900, toYear: 300 }
|
|
225
|
+
* // After calling initializeYears(), 'years' might contain [1900, 1901, ..., 300]
|
|
226
|
+
* this.initializeYears();
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
initializeYears() {
|
|
230
|
+
this.years = Array.from({ length: this.yearsRange.toYear }, (_, index) => index + this.yearsRange.startYear);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Toggle the editing mode for the date input. When enabled, the user can edit the date directly in the input field.
|
|
234
|
+
* This method sets the 'isEditing' flag to true and stores the current formatted date for editing.
|
|
235
|
+
*/
|
|
236
|
+
toggleEdit() {
|
|
237
|
+
this.isEditing = true;
|
|
238
|
+
this.editedDate = this.formatSelectedDate(); // Store the current formatted date for editing
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get a list of month names in the specified language and format.
|
|
242
|
+
* @param locales - An optional parameter specifying the locale or locales to use for formatting.
|
|
243
|
+
* @param format - The format for month names, either "long" (default) or "short".
|
|
244
|
+
* @returns An array of month names based on the provided format and locale.
|
|
245
|
+
* ```
|
|
246
|
+
* // Get a list of month names in the default language and long format
|
|
247
|
+
* const months = this.getMonthList(this.lang);
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
getMonthList(locales, format = "long") {
|
|
251
|
+
const year = new Date().getFullYear();
|
|
252
|
+
const monthList = [...Array(12).keys()];
|
|
253
|
+
const formatter = new Intl.DateTimeFormat(locales, { month: format });
|
|
254
|
+
const getMonthName = (monthIndex) => formatter.format(new Date(year, monthIndex));
|
|
255
|
+
return monthList.map(getMonthName);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Get a list of weekday names in the specified language and format.
|
|
259
|
+
* @param locales - An optional parameter specifying the locale or locales to use for formatting.
|
|
260
|
+
* @param format - The format for weekday names, either "short" (default) or "long".
|
|
261
|
+
* @returns An array of weekday names based on the provided format and locale.
|
|
262
|
+
* ```
|
|
263
|
+
* // Get a list of weekday names in the default language and short format
|
|
264
|
+
* const weekdays = this.getWeekdayList();
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
getWeekdayList(locales, format = "short") {
|
|
268
|
+
const weekdays = [...Array(7).keys()];
|
|
269
|
+
const mondayIndex = weekdays.indexOf(0);
|
|
270
|
+
weekdays.splice(mondayIndex, 1);
|
|
271
|
+
weekdays.push(0);
|
|
272
|
+
const formatter = new Intl.DateTimeFormat(locales, { weekday: format });
|
|
273
|
+
const getWeekdayName = (weekdayIndex) => {
|
|
274
|
+
return formatter.format(new Date(2023, 9, weekdayIndex + 1));
|
|
275
|
+
};
|
|
276
|
+
return weekdays.map(getWeekdayName);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Toggle the visibility of the calendar component. When called, this method changes the 'isCalendarOpen' flag
|
|
280
|
+
* to show or hide the calendar interface.
|
|
281
|
+
* ```
|
|
282
|
+
* // Toggle the visibility of the calendar
|
|
283
|
+
* this.toggleCalendar();
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
toggleCalendar() {
|
|
287
|
+
this.isCalendarOpen = !this.isCalendarOpen;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Save the edited date input by the user, provided it matches the specified date format.
|
|
291
|
+
* This method checks if the entered date is in a valid format, disables the editing mode, and applies
|
|
292
|
+
* the edited date to the 'selectedDate'. It then reformats the selected date and closes the calendar.
|
|
293
|
+
* ```
|
|
294
|
+
* // Save the edited date and update the selected date
|
|
295
|
+
* this.saveEditedDate();
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
saveEditedDate() {
|
|
299
|
+
if (this.isDateValid(this.editedDate)) {
|
|
300
|
+
this.isEditing = false;
|
|
301
|
+
const [day, month, year] = this.editedDate.split('/');
|
|
302
|
+
this.selectedDate = new Date(+year, +month - 1, +day);
|
|
303
|
+
this.formatDate();
|
|
304
|
+
this.toggleCalendar();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Handle user input in the editable input field for date editing. This method captures the input value
|
|
309
|
+
* and stores it in the 'editedDate' variable. If the input matches the valid date format, it updates
|
|
310
|
+
* 'selectedDateMonth' and 'selectedDateYear' accordingly.
|
|
311
|
+
* @param event - The input event containing the user's input.
|
|
312
|
+
* ```
|
|
313
|
+
* // Handle user input in the editable input field
|
|
314
|
+
* this.onDateInput(event);
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
onDateInput(event) {
|
|
318
|
+
const inputDate = event.target.value;
|
|
319
|
+
if (this.isDateValid(inputDate)) {
|
|
320
|
+
this.editedDate = inputDate;
|
|
321
|
+
const parsedDate = inputDate.split('/');
|
|
322
|
+
this.selectedDateMonth = +parsedDate[1] - 1;
|
|
323
|
+
this.selectedDateYear = +parsedDate[2];
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Toggle the visibility of the month dropdown in the calendar interface.
|
|
328
|
+
* This method is used to open or close the dropdown for selecting months.
|
|
329
|
+
* @param event - The event triggering the toggle action (e.g., a click event).
|
|
330
|
+
* ```
|
|
331
|
+
* // Toggle the visibility of the month dropdown
|
|
332
|
+
* this.toggleMonthDropdown(event);
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
toggleMonthDropdown(event) {
|
|
336
|
+
this.isMonthDropdownOpen = !this.isMonthDropdownOpen;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Toggle the visibility of the year dropdown in the calendar interface.
|
|
340
|
+
* This method is used to open or close the dropdown for selecting years.
|
|
341
|
+
* @param event - The event triggering the toggle action (e.g., a click event).
|
|
342
|
+
* ```
|
|
343
|
+
* // Toggle the visibility of the year dropdown
|
|
344
|
+
* this.toggleYearDropdown(event);
|
|
345
|
+
* ```
|
|
346
|
+
*/
|
|
347
|
+
toggleYearDropdown(event) {
|
|
348
|
+
this.isYearDropdownOpen = !this.isYearDropdownOpen;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Handle the change of the selected month in the calendar interface.
|
|
352
|
+
* This method updates the input value, sets the selected date to the first day of the chosen month,
|
|
353
|
+
* and recalculates the calendar display accordingly.
|
|
354
|
+
* ```
|
|
355
|
+
* // Handle the change of the selected month
|
|
356
|
+
* this.onMonthChange();
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
359
|
+
onMonthChange() {
|
|
360
|
+
this.updateInputValue();
|
|
361
|
+
this.selectedDate = new Date(this.selectedDateYear, this.selectedDateMonth, 1);
|
|
362
|
+
this.calculateFirstDayOfCalendar();
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Handle the change of the selected year in the calendar interface.
|
|
366
|
+
* This method updates the input value, sets the selected date to the first day of the chosen year,
|
|
367
|
+
* reformats the selected date, and recalculates the calendar display.
|
|
368
|
+
* ```
|
|
369
|
+
* // Handle the change of the selected year
|
|
370
|
+
* this.onYearChange();
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
onYearChange() {
|
|
374
|
+
this.updateInputValue();
|
|
375
|
+
this.selectedDate = new Date(this.selectedDateYear, this.selectedDateMonth, 1);
|
|
376
|
+
this.formatDate();
|
|
377
|
+
this.calculateFirstDayOfCalendar();
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Select a date in the calendar interface and perform necessary updates.
|
|
381
|
+
* This method sets the selected date, formats it, closes the calendar, and emits a dateChanged event.
|
|
382
|
+
* It also updates the selected month and year dropdown values.
|
|
383
|
+
* @param date - The date to be selected in the calendar.
|
|
384
|
+
*/
|
|
385
|
+
selectDate(date) {
|
|
386
|
+
this.selectedDate = date;
|
|
387
|
+
this.formatDate();
|
|
388
|
+
this.isCalendarOpen = false;
|
|
389
|
+
this.dateChanged.next(this.selectedDate);
|
|
390
|
+
this.selectedDateMonth = this.selectedDate.getMonth();
|
|
391
|
+
this.selectedDateYear = this.selectedDate.getFullYear();
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Format the selected date based on the chosen date format and language.
|
|
395
|
+
* This method uses the Angular DatePipe to format the selected date and updates the formattedDate variable.
|
|
396
|
+
* ```
|
|
397
|
+
* // Format the selected date
|
|
398
|
+
* this.formatDate();
|
|
399
|
+
* ```
|
|
400
|
+
*/
|
|
401
|
+
formatDate() {
|
|
402
|
+
this.formattedDate = this.datePipe.transform(this.selectedDate, this.dateFormat) || '';
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Format the selected date based on the chosen date format, language, and locale.
|
|
406
|
+
* This method uses the Angular DatePipe to format the selected date with the specified language and updates the formatted date as a string.
|
|
407
|
+
* @returns A formatted date string.
|
|
408
|
+
* ```
|
|
409
|
+
* // Format the selected date with language
|
|
410
|
+
* const formatted = this.formatSelectedDate();
|
|
411
|
+
* ```
|
|
412
|
+
*/
|
|
413
|
+
formatSelectedDate() {
|
|
414
|
+
return this.datePipe.transform(this.selectedDate, this.dateFormat, this.lang) || '';
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Update the input value displayed in the calendar interface.
|
|
418
|
+
* This method updates the input value to either the edited date or the formatted selected date,
|
|
419
|
+
* depending on whether the user is in edit mode or not.
|
|
420
|
+
* ```
|
|
421
|
+
* // Update the input value
|
|
422
|
+
* this.updateInputValue();
|
|
423
|
+
* ```
|
|
424
|
+
*/
|
|
425
|
+
updateInputValue() {
|
|
426
|
+
this.formattedDate = this.isEditing ? this.editedDate : this.formatSelectedDate();
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Get an array of arrays representing the days of the current month.
|
|
430
|
+
* Each sub-array contains the day data for a week, and each day data object includes the date and whether it belongs to the current month.
|
|
431
|
+
* @returns An array of arrays representing the days of the current month.
|
|
432
|
+
* ```
|
|
433
|
+
* // Get an array of arrays representing the days of the current month
|
|
434
|
+
* const calendar = this.calendarDays;
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
get calendarDays() {
|
|
438
|
+
return this.calculateFirstDayOfCalendar();
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Get the date of the previous month to display in empty cells of the current month.
|
|
442
|
+
* This method returns the date of the previous month if the provided date is not in the current month.
|
|
443
|
+
* If the provided date is in the current month, it returns the date's day as a string.
|
|
444
|
+
* @param date - The date to evaluate.
|
|
445
|
+
* @returns The date of the previous month or a day string.
|
|
446
|
+
* ```
|
|
447
|
+
* // Get the previous month's date to display in empty cells
|
|
448
|
+
* const previousMonthDate = this.getPreviousMonthDate(new Date(2023, 8, 1));
|
|
449
|
+
* ```
|
|
450
|
+
*/
|
|
451
|
+
getPreviousMonthDate(date) {
|
|
452
|
+
if (!date) {
|
|
453
|
+
return '';
|
|
454
|
+
}
|
|
455
|
+
const currentDate = new Date();
|
|
456
|
+
if (date.getMonth() === currentDate.getMonth() && date.getFullYear() === currentDate.getFullYear()) {
|
|
457
|
+
return date.getDate().toString();
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
return this.datePipe.transform(date, 'dd');
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Navigate to the previous month in the calendar interface.
|
|
465
|
+
* This method updates the selectedDate, formats it, and recalculates the first day of the calendar.
|
|
466
|
+
* ```
|
|
467
|
+
* // Navigate to the previous month
|
|
468
|
+
* this.getPreviousMonth();
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
getPreviousMonth() {
|
|
472
|
+
const currentMonth = this.selectedDate.getMonth();
|
|
473
|
+
this.selectedDate = new Date(this.selectedDate.getFullYear(), currentMonth - 1, 1);
|
|
474
|
+
this.formatDate();
|
|
475
|
+
this.calculateFirstDayOfCalendar();
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Navigate to the next month in the calendar interface.
|
|
479
|
+
* This method updates the selectedDate, formats it, and recalculates the first day of the calendar.
|
|
480
|
+
* ```
|
|
481
|
+
* // Navigate to the next month
|
|
482
|
+
* this.getNextMonth();
|
|
483
|
+
* ```
|
|
484
|
+
*/
|
|
485
|
+
getNextMonth() {
|
|
486
|
+
const currentMonth = this.selectedDate.getMonth();
|
|
487
|
+
this.selectedDate = new Date(this.selectedDate.getFullYear(), currentMonth + 1, 1);
|
|
488
|
+
this.formatDate();
|
|
489
|
+
this.calculateFirstDayOfCalendar();
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Get the number of days in a given month of a specific year.
|
|
493
|
+
* @param year - The year for which you want to determine the number of days.
|
|
494
|
+
* @param month - The month (0-based index) for which you want to determine the number of days.
|
|
495
|
+
* @returns The number of days in the specified month of the given year.
|
|
496
|
+
*/
|
|
497
|
+
daysInMonth(year, month) {
|
|
498
|
+
return new Date(year, month + 1, 0).getDate();
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Calculate the structure of days in a month for the calendar display.
|
|
502
|
+
* This method generates a matrix of day data objects representing the days in the calendar.
|
|
503
|
+
* Each day data object contains the date and whether it belongs to the current month.
|
|
504
|
+
* @returns A matrix of day data objects for the calendar display.
|
|
505
|
+
*/
|
|
506
|
+
calculateFirstDayOfCalendar() {
|
|
507
|
+
const year = this.selectedDate.getFullYear();
|
|
508
|
+
const month = this.selectedDate.getMonth();
|
|
509
|
+
const firstDayOfMonth = new Date(year, month, 1);
|
|
510
|
+
const firstWeekday = firstDayOfMonth.getDay();
|
|
511
|
+
const startDay = firstWeekday === 0 ? -5 : 2 - firstWeekday;
|
|
512
|
+
const calendarDays = [];
|
|
513
|
+
let currentDay = startDay;
|
|
514
|
+
for (let i = 0; i < 6; i++) {
|
|
515
|
+
const week = [];
|
|
516
|
+
for (let j = 0; j < 7; j++) {
|
|
517
|
+
const day = new Date(year, month, currentDay);
|
|
518
|
+
const dayData = {
|
|
519
|
+
date: day,
|
|
520
|
+
isCurrentMonth: currentDay >= 1 && currentDay <= this.daysInMonth(year, month),
|
|
521
|
+
};
|
|
522
|
+
week.push(dayData);
|
|
523
|
+
currentDay++;
|
|
524
|
+
}
|
|
525
|
+
calendarDays.push(week);
|
|
526
|
+
}
|
|
527
|
+
return calendarDays;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Check if a given date is the currently selected date in the calendar.
|
|
531
|
+
* @param date - The date to check.
|
|
532
|
+
* @returns `true` if the provided date matches the selected date, otherwise `false`.
|
|
533
|
+
* ```
|
|
534
|
+
* // Check if a date is selected
|
|
535
|
+
* const isSelected = this.isDateSelected(someDate);
|
|
536
|
+
* ```
|
|
537
|
+
*/
|
|
538
|
+
isDateSelected(date) {
|
|
539
|
+
return date.toDateString() === this.selectedDate.toDateString();
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Check if a date string is valid based on the specified date format.
|
|
543
|
+
* @param inputDate - The date string to validate.
|
|
544
|
+
* @returns `true` if the input date string is valid, otherwise `false`.
|
|
545
|
+
* ```
|
|
546
|
+
* // Check if a date string is valid
|
|
547
|
+
* const isValidDate = this.isDateValid('05/25/2023');
|
|
548
|
+
* ```
|
|
549
|
+
*/
|
|
550
|
+
isDateValid(inputDate) {
|
|
551
|
+
return this.dateRegExp.test(inputDate);
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Check if a given date is today's date.
|
|
555
|
+
* @param date - The date to check.
|
|
556
|
+
* @returns `true` if the provided date is today's date, otherwise `false`.
|
|
557
|
+
* ```
|
|
558
|
+
* // Check if a date is today's date
|
|
559
|
+
* const isToday = this.isDateToday(someDate);
|
|
560
|
+
* ```
|
|
561
|
+
*/
|
|
562
|
+
isDateToday(date) {
|
|
563
|
+
const today = new Date();
|
|
564
|
+
return date.toDateString() === today.toDateString();
|
|
565
|
+
}
|
|
566
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: DatepickerComponent, deps: [{ token: i1.DatePipe }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
567
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.6", type: DatepickerComponent, selector: "mefdev-datepicker", inputs: { lang: "lang", dateFormat: "dateFormat", yearsRange: ["range", "yearsRange"], disabled: "disabled", topOffset: "topOffset", leftOffset: "leftOffset" }, outputs: { dateChanged: "dateChanged" }, host: { listeners: { "document:click": "onClick($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"datepicker-container\"\r\n[class.disabled]=\"disabled\"\r\n>\r\n\r\n <!-- Input, save & edit buttons -->\r\n <div class=\"input-container\">\r\n\r\n <div *ngIf=\"!isEditing\">\r\n\r\n <input\r\n type=\"text\"\r\n (click)=\"toggleCalendar()\"\r\n [value]=\"formattedDate\"\r\n [readOnly]=\"true\"\r\n [disabled]=\"isEditing\"\r\n >\r\n </div>\r\n <!-- Edit -->\r\n <i class=\"fa fa-pencil-square-o edit-button\" aria-hidden=\"true\" (click)=\"toggleEdit()\"></i> \r\n\r\n <div *ngIf=\"isEditing\">\r\n <input\r\n type=\"text\"\r\n [value]=\"editedDate\"\r\n (input)=\"onDateInput($event)\"\r\n class=\"border-3\"\r\n (click)=\"toggleCalendar()\"\r\n >\r\n <i class=\"fa fa-floppy-o edit-button\" (click)=\"saveEditedDate()\" aria-hidden=\"true\"></i>\r\n </div> \r\n </div>\r\n\r\n<!-- Calendar(Dropdowns, dates) -->\r\n <div *ngIf=\"isCalendarOpen\" class=\"calendar\" #calendarContainer \r\n [style.top]=\"topOffset\"\r\n [style.left]=\"leftOffset\">\r\n <div class=\"calendar-header\">\r\n <div class=\"monthButtonContainer\">\r\n <!-- Month dropdown -->\r\n <ng-container *ngIf=\"isMonthDropdownOpen; else monthLabel\">\r\n <mefdev-select \r\n class=\"monthDropdown\"\r\n [(ngModel)]=\"selectedDateMonth\" \r\n (ngModelChange)=\"onMonthChange()\"\r\n [PlaceHolder]=\"'month'\"\r\n >\r\n <mefdev-option \r\n *ngFor=\"let month of months; let i = index\" \r\n [Value]=\"i\"\r\n [Label] = \"month\" \r\n \r\n >{{ month }}</mefdev-option>\r\n </mefdev-select>\r\n </ng-container>\r\n <ng-template #monthLabel>\r\n <span (click)=\"toggleMonthDropdown($event)\"></span>\r\n </ng-template>\r\n\r\n <!-- Year dropdown -->\r\n <ng-container *ngIf=\"isYearDropdownOpen; else yearLabel\">\r\n <mefdev-select \r\n class=\"yearDropdown\" \r\n [(ngModel)]=\"selectedDateYear\" \r\n (ngModelChange)=\"onYearChange()\"\r\n [PlaceHolder]=\"'year'\"\r\n >\r\n <mefdev-option \r\n *ngFor=\"let year of years\" \r\n [Label] = \"year\" \r\n [Value]=\"year\" \r\n >{{year}}</mefdev-option>\r\n </mefdev-select>\r\n </ng-container>\r\n <ng-template #yearLabel>\r\n <span (click)=\"toggleYearDropdown($event)\">{{ selectedDateYear }}</span>\r\n </ng-template>\r\n </div>\r\n <!-- Calendar exit button -->\r\n <div>\r\n <i class=\"fa fa-times toggleCalendarButton\" (click)=\"toggleCalendar()\" aria-hidden=\"true\"></i>\r\n </div>\r\n </div>\r\n \r\n <div class=\"calendar-body\">\r\n <table>\r\n <tr>\r\n <th class=\"align-items-center\" *ngFor=\"let weekday of weekdays\">{{ weekday }}</th>\r\n </tr>\r\n <tr *ngFor=\"let week of calendarDays\">\r\n <td *ngFor=\"let dayData of week\" \r\n (click)=\"selectDate(dayData.date)\"\r\n [ngClass]=\"{ 'selected': isDateSelected(dayData.date), 'prev-month': !dayData.isCurrentMonth }\">\r\n\r\n <span class=\"date\" \r\n [class.prev-month]=\"!dayData.isCurrentMonth\"\r\n >\r\n {{ dayData.date.getDate() }}\r\n </span>\r\n </td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [".color-Dark-Gray-1{color:#373737!important}.color-Dark-Gray-2{color:#4d4d4d!important}.color-Red{color:#cf0106!important}.color-Green{color:#28b446!important}.color-Light-Gray-1{color:#929292!important}.color-Light-Gray-2{color:#eaeaea!important}.color-Light-Gray-3{color:#f3f3f3!important}.color-White{color:#fff!important}.color-Link{color:#0185cf!important}.b-color-Dark-Gray-1{background-color:#373737!important}.b-color-Dark-Gray-2{background-color:#4d4d4d!important}.b-color-Red{background-color:#cf0106!important}.b-color-Green{background-color:#28b446!important}.b-color-Light-Gray-1{background-color:#929292!important}.b-color-Light-Gray-2{background-color:#eaeaea!important}.b-color-Light-Gray-3{background-color:#f3f3f3!important}.b-color-White{background-color:#fff!important}.b-color-Link{background-color:#0185cf!important}.datepicker-container{position:relative;display:inline-block}.datepicker-container.disabled{pointer-events:none;opacity:.8}.input-container{position:relative;display:inline-block}.input-container input[type=text]{cursor:pointer;padding:5px;border:1px solid #929292;border-radius:4px}.input-container input[type=text]:hover{border:1px solid #4D4D4D}.input-container .edit-button{position:absolute;top:0;right:0;height:100%;margin:0;padding:5px 10px;background-color:#eaeaea;border:1px solid #929292;border-left:none;border-radius:0 4px 4px 0;cursor:pointer;display:flex;justify-content:center;align-items:center}.calendar{position:absolute;top:35px;left:10%;border:1px solid #929292;background-color:#eaeaea;border-radius:4px;z-index:1}.calendar .calendar-header{background-color:#fff;text-align:center;justify-content:space-between;display:flex;padding:5px 0}.calendar .calendar-header i.fa{display:flex;justify-content:center;align-items:center;width:30px;height:30px;font-size:20px;border-radius:50%;cursor:pointer;background-color:transparent;border:none;color:#cf0106}.calendar .calendar-header .monthButtonContainer{padding-left:10px;height:45px;min-width:140px;display:flex;align-items:center}.calendar .calendar-header .monthDropdown,.calendar .calendar-header .yearDropdown{height:45px;width:105px;cursor:pointer;display:inline-block;padding:6px 5px;border:1px solid #EAEAEA;border-radius:4px;background-color:#fff;color:#4d4d4d}.calendar .calendar-header .monthDropdown{margin:0 8px 0 0;width:130px}.calendar .calendar-header .monthDropdown:hover,.calendar .calendar-header .yearDropdown:hover{border-color:#f3f3f3}.calendar .calendar-body{padding:5px;width:260px}.calendar .calendar-body td{padding:10px;position:relative}.calendar .calendar-body td.selected{position:relative;color:#fff}.calendar .calendar-body td.selected:before{content:\"\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border-radius:20%;background-color:#cf0106;z-index:-1;width:30px;height:30px;color:#fff;border:1px solid #373737}.calendar .calendar-body td:hover{color:#fff;font-weight:700;background-color:#929292;border-radius:20%;cursor:pointer}.calendar .calendar-body .date{display:flex;justify-content:center}.calendar .calendar-body .date.prev-month{color:#f3f3f3}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MefDevOptionComponent, selector: "mefdev-option", inputs: ["Value", "Label", "Disabled"] }, { kind: "component", type: i4.MefDevSelectComponent, selector: "mefdev-select", inputs: ["Filter", "MaxMultiple", "FirstDefault", "AllowClear", "KeepUnListOptions", "Mode", "Multiple", "PlaceHolder", "NotFoundContent", "Size", "ShowSearch", "Tags", "Disabled", "Open"], outputs: ["SearchChange", "change", "OpenChange", "ScrollToBottom"] }] });
|
|
568
|
+
}
|
|
569
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: DatepickerComponent, decorators: [{
|
|
570
|
+
type: Component,
|
|
571
|
+
args: [{ selector: 'mefdev-datepicker', template: "<div class=\"datepicker-container\"\r\n[class.disabled]=\"disabled\"\r\n>\r\n\r\n <!-- Input, save & edit buttons -->\r\n <div class=\"input-container\">\r\n\r\n <div *ngIf=\"!isEditing\">\r\n\r\n <input\r\n type=\"text\"\r\n (click)=\"toggleCalendar()\"\r\n [value]=\"formattedDate\"\r\n [readOnly]=\"true\"\r\n [disabled]=\"isEditing\"\r\n >\r\n </div>\r\n <!-- Edit -->\r\n <i class=\"fa fa-pencil-square-o edit-button\" aria-hidden=\"true\" (click)=\"toggleEdit()\"></i> \r\n\r\n <div *ngIf=\"isEditing\">\r\n <input\r\n type=\"text\"\r\n [value]=\"editedDate\"\r\n (input)=\"onDateInput($event)\"\r\n class=\"border-3\"\r\n (click)=\"toggleCalendar()\"\r\n >\r\n <i class=\"fa fa-floppy-o edit-button\" (click)=\"saveEditedDate()\" aria-hidden=\"true\"></i>\r\n </div> \r\n </div>\r\n\r\n<!-- Calendar(Dropdowns, dates) -->\r\n <div *ngIf=\"isCalendarOpen\" class=\"calendar\" #calendarContainer \r\n [style.top]=\"topOffset\"\r\n [style.left]=\"leftOffset\">\r\n <div class=\"calendar-header\">\r\n <div class=\"monthButtonContainer\">\r\n <!-- Month dropdown -->\r\n <ng-container *ngIf=\"isMonthDropdownOpen; else monthLabel\">\r\n <mefdev-select \r\n class=\"monthDropdown\"\r\n [(ngModel)]=\"selectedDateMonth\" \r\n (ngModelChange)=\"onMonthChange()\"\r\n [PlaceHolder]=\"'month'\"\r\n >\r\n <mefdev-option \r\n *ngFor=\"let month of months; let i = index\" \r\n [Value]=\"i\"\r\n [Label] = \"month\" \r\n \r\n >{{ month }}</mefdev-option>\r\n </mefdev-select>\r\n </ng-container>\r\n <ng-template #monthLabel>\r\n <span (click)=\"toggleMonthDropdown($event)\"></span>\r\n </ng-template>\r\n\r\n <!-- Year dropdown -->\r\n <ng-container *ngIf=\"isYearDropdownOpen; else yearLabel\">\r\n <mefdev-select \r\n class=\"yearDropdown\" \r\n [(ngModel)]=\"selectedDateYear\" \r\n (ngModelChange)=\"onYearChange()\"\r\n [PlaceHolder]=\"'year'\"\r\n >\r\n <mefdev-option \r\n *ngFor=\"let year of years\" \r\n [Label] = \"year\" \r\n [Value]=\"year\" \r\n >{{year}}</mefdev-option>\r\n </mefdev-select>\r\n </ng-container>\r\n <ng-template #yearLabel>\r\n <span (click)=\"toggleYearDropdown($event)\">{{ selectedDateYear }}</span>\r\n </ng-template>\r\n </div>\r\n <!-- Calendar exit button -->\r\n <div>\r\n <i class=\"fa fa-times toggleCalendarButton\" (click)=\"toggleCalendar()\" aria-hidden=\"true\"></i>\r\n </div>\r\n </div>\r\n \r\n <div class=\"calendar-body\">\r\n <table>\r\n <tr>\r\n <th class=\"align-items-center\" *ngFor=\"let weekday of weekdays\">{{ weekday }}</th>\r\n </tr>\r\n <tr *ngFor=\"let week of calendarDays\">\r\n <td *ngFor=\"let dayData of week\" \r\n (click)=\"selectDate(dayData.date)\"\r\n [ngClass]=\"{ 'selected': isDateSelected(dayData.date), 'prev-month': !dayData.isCurrentMonth }\">\r\n\r\n <span class=\"date\" \r\n [class.prev-month]=\"!dayData.isCurrentMonth\"\r\n >\r\n {{ dayData.date.getDate() }}\r\n </span>\r\n </td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [".color-Dark-Gray-1{color:#373737!important}.color-Dark-Gray-2{color:#4d4d4d!important}.color-Red{color:#cf0106!important}.color-Green{color:#28b446!important}.color-Light-Gray-1{color:#929292!important}.color-Light-Gray-2{color:#eaeaea!important}.color-Light-Gray-3{color:#f3f3f3!important}.color-White{color:#fff!important}.color-Link{color:#0185cf!important}.b-color-Dark-Gray-1{background-color:#373737!important}.b-color-Dark-Gray-2{background-color:#4d4d4d!important}.b-color-Red{background-color:#cf0106!important}.b-color-Green{background-color:#28b446!important}.b-color-Light-Gray-1{background-color:#929292!important}.b-color-Light-Gray-2{background-color:#eaeaea!important}.b-color-Light-Gray-3{background-color:#f3f3f3!important}.b-color-White{background-color:#fff!important}.b-color-Link{background-color:#0185cf!important}.datepicker-container{position:relative;display:inline-block}.datepicker-container.disabled{pointer-events:none;opacity:.8}.input-container{position:relative;display:inline-block}.input-container input[type=text]{cursor:pointer;padding:5px;border:1px solid #929292;border-radius:4px}.input-container input[type=text]:hover{border:1px solid #4D4D4D}.input-container .edit-button{position:absolute;top:0;right:0;height:100%;margin:0;padding:5px 10px;background-color:#eaeaea;border:1px solid #929292;border-left:none;border-radius:0 4px 4px 0;cursor:pointer;display:flex;justify-content:center;align-items:center}.calendar{position:absolute;top:35px;left:10%;border:1px solid #929292;background-color:#eaeaea;border-radius:4px;z-index:1}.calendar .calendar-header{background-color:#fff;text-align:center;justify-content:space-between;display:flex;padding:5px 0}.calendar .calendar-header i.fa{display:flex;justify-content:center;align-items:center;width:30px;height:30px;font-size:20px;border-radius:50%;cursor:pointer;background-color:transparent;border:none;color:#cf0106}.calendar .calendar-header .monthButtonContainer{padding-left:10px;height:45px;min-width:140px;display:flex;align-items:center}.calendar .calendar-header .monthDropdown,.calendar .calendar-header .yearDropdown{height:45px;width:105px;cursor:pointer;display:inline-block;padding:6px 5px;border:1px solid #EAEAEA;border-radius:4px;background-color:#fff;color:#4d4d4d}.calendar .calendar-header .monthDropdown{margin:0 8px 0 0;width:130px}.calendar .calendar-header .monthDropdown:hover,.calendar .calendar-header .yearDropdown:hover{border-color:#f3f3f3}.calendar .calendar-body{padding:5px;width:260px}.calendar .calendar-body td{padding:10px;position:relative}.calendar .calendar-body td.selected{position:relative;color:#fff}.calendar .calendar-body td.selected:before{content:\"\";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border-radius:20%;background-color:#cf0106;z-index:-1;width:30px;height:30px;color:#fff;border:1px solid #373737}.calendar .calendar-body td:hover{color:#fff;font-weight:700;background-color:#929292;border-radius:20%;cursor:pointer}.calendar .calendar-body .date{display:flex;justify-content:center}.calendar .calendar-body .date.prev-month{color:#f3f3f3}\n"] }]
|
|
572
|
+
}], ctorParameters: function () { return [{ type: i1.DatePipe }, { type: i0.ElementRef }]; }, propDecorators: { lang: [{
|
|
573
|
+
type: Input
|
|
574
|
+
}], dateFormat: [{
|
|
575
|
+
type: Input
|
|
576
|
+
}], yearsRange: [{
|
|
577
|
+
type: Input,
|
|
578
|
+
args: ['range']
|
|
579
|
+
}], disabled: [{
|
|
580
|
+
type: Input
|
|
581
|
+
}], topOffset: [{
|
|
582
|
+
type: Input
|
|
583
|
+
}], leftOffset: [{
|
|
584
|
+
type: Input
|
|
585
|
+
}], dateChanged: [{
|
|
586
|
+
type: Output
|
|
587
|
+
}], onClick: [{
|
|
588
|
+
type: HostListener,
|
|
589
|
+
args: ['document:click', ['$event']]
|
|
590
|
+
}] } });
|
|
591
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS1raXQtbGliL3NyYy9saWIvbWFya3VwLWtpdC91dGlscy9kYXRlcGlja2VyL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS1raXQtbGliL3NyYy9saWIvbWFya3VwLWtpdC91dGlscy9kYXRlcGlja2VyL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUF5QixZQUFZLEVBQWEsS0FBSyxFQUFxQixNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7Ozs7QUFJMUk7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQWtCRTtBQVFGLE1BQU0sT0FBTyxtQkFBbUI7SUFxTFY7SUFBNEI7SUFuTGxEOzs7TUFHRTtJQUNGLGNBQWMsR0FBWSxLQUFLLENBQUM7SUFFaEM7OztNQUdFO0lBQ0YsU0FBUyxHQUFZLEtBQUssQ0FBQztJQUUzQjs7O01BR0U7SUFDRixZQUFZLEdBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQztJQUUvQjs7O0tBR0M7SUFDRixhQUFhLENBQU87SUFFbkI7OztLQUdDO0lBQ0YsVUFBVSxHQUFXLEVBQUUsQ0FBQztJQUV4Qjs7O01BR0U7SUFDRixtQkFBbUIsR0FBWSxJQUFJLENBQUM7SUFFcEM7OztNQUdFO0lBQ0Ysa0JBQWtCLEdBQVksSUFBSSxDQUFDO0lBRW5DOzs7TUFHRTtJQUNGLGlCQUFpQixHQUFXLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUM7SUFFekQ7OztNQUdFO0lBQ0YsZ0JBQWdCLEdBQVcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUUxRDs7O0tBR0M7SUFD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Q1EsY0FBYyxDQUFDLElBQVU7UUFDL0IsT0FBTyxJQUFJLENBQUMsWUFBWSxFQUFFLEtBQUssSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUNsRSxDQUFDO0lBRUg7Ozs7Ozs7O01BUUU7SUFDUSxXQUFXLENBQUMsU0FBaUI7UUFDbkMsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRUg7Ozs7Ozs7O01BUUU7SUFDUSxXQUFXLENBQUMsSUFBVTtRQUM1QixNQUFNLEtBQUssR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLFlBQVksRUFBRSxLQUFLLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0RCxDQUFDO3VHQXprQlUsbUJBQW1COzJGQUFuQixtQkFBbUIsc1ZDOUJoQyw2dkhBeUdBOzsyRkQzRWEsbUJBQW1CO2tCQU4vQixTQUFTOytCQUNFLG1CQUFtQjt3SEEyRXRCLElBQUk7c0JBQVosS0FBSztnQkFVRyxVQUFVO3NCQUFsQixLQUFLO2dCQVVVLFVBQVU7c0JBQXpCLEtBQUs7dUJBQUMsT0FBTztnQkFVTCxRQUFRO3NCQUFoQixLQUFLO2dCQVVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBVUcsVUFBVTtzQkFBbEIsS0FBSztnQkFVSSxXQUFXO3NCQUFwQixNQUFNO2dCQTBCTCxPQUFPO3NCQUROLFlBQVk7dUJBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBPbkRlc3Ryb3ksIElucHV0LCBPbkNoYW5nZXMsIE9uSW5pdCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRGF0ZVBpcGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5cclxuXHJcbi8qKlxyXG4gICogRGF0ZXBpY2tlciBDb21wb25lbnQgZm9yIHNlbGVjdGluZyBkYXRlcy5cclxuICAqXHJcbiAgKiBUaGlzIGNvbXBvbmVudCBhbGxvd3MgdXNlcnMgdG8gcGljayBhIGRhdGUgZnJvbSBhIGNhbGVuZGFyIGludGVyZmFjZS5cclxuICAqIEl0IHN1cHBvcnRzIHZhcmlvdXMgY29uZmlndXJhdGlvbiBvcHRpb25zIHN1Y2ggYXMgbGFuZ3VhZ2UsIGRhdGUgZm9ybWF0LCBhbmQgZGF0ZSByYW5nZS5cclxuICAqXHJcbiAgKiBAZXhhbXBsZVxyXG4gICogPG1lZmRldi1kYXRlcGlja2VyXHJcbiAgKiAgIFtsYW5nXT1cIid1aydcIlxyXG4gICogICBbZGF0ZUZvcm1hdF09XCInZGQvTU0veXl5eSdcIlxyXG4gICogICBbcmFuZ2VdPVwie3N0YXJ0WWVhcjogMTkwMCwgdG9ZZWFyOiAzMDB9XCJcclxuICAqICAgW2Rpc2FibGVkXT1cImZhbHNlXCJcclxuICAqICAgKGRhdGVDaGFuZ2VkKT1cIm9uRGF0ZUNoYW5nZWQoJGV2ZW50KVwiXHJcbiAgKiAgIFt0b3BPZmZzZXRdPVwiJzIwJ1wiXHJcbiAgKiAgIFtsZWZ0T2Zmc2V0XT1cIicxMCdcIj5cclxuICAqIDwvbWVmZGV2LWRhdGVwaWNrZXI+XHJcbiAgKlxyXG4gICogPGV4YW1wbGUtdXJsPmh0dHBzOi8vbWVmLmRldi91aV9raXRfZGVtby92aWV3L3V0aWxzL2RhdGVwaWNrZXI8L2V4YW1wbGUtdXJsPlxyXG4qL1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdtZWZkZXYtZGF0ZXBpY2tlcicsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2RhdGVwaWNrZXIuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2RhdGVwaWNrZXIuY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5cclxuZXhwb3J0IGNsYXNzIERhdGVwaWNrZXJDb21wb25lbnQgaW1wbGVtZW50cyAgT25DaGFuZ2VzLCBPbkluaXQge1xyXG5cclxuLyoqXHJcbiAqIEZsYWcgdG8gZGV0ZXJtaW5lIGlmIHRoZSBjYWxlbmRhciBpcyBvcGVuIG9yIGNsb3NlZC5cclxuICogRGVmYXVsdCB2YWx1ZTogZmFsc2UgKGNsb3NlZCkuXHJcbiovXHJcbmlzQ2FsZW5kYXJPcGVuOiBib29sZWFuID0gZmFsc2U7IFxyXG5cclxuLyoqXHJcbiAqIEZsYWcgdG8gZGV0ZXJtaW5lIGlmIHRoZSBjb21wb25lbnQgaXMgaW4gZWRpdGluZyBtb2RlLlxyXG4gKiBEZWZhdWx0IHZhbHVlOiBmYWxzZSAobm90IGluIGVkaXRpbmcgbW9kZSkuXHJcbiovXHJcbmlzRWRpdGluZzogYm9vbGVhbiA9IGZhbHNlOyAgXHJcblxyXG4vKipcclxuICogVGhlIGN1cnJlbnRseSBzZWxlY3RlZCBkYXRlLlxyXG4gKiBEZWZhdWx0IHZhbHVlOiBUb2RheSdzIGRhdGUuXHJcbiovXHJcbnNlbGVjdGVkRGF0ZTogRGF0ZSA9IG5ldyBEYXRlKCk7IFxyXG5cclxuIC8qKlxyXG4gKiBUaGUgZm9ybWF0dGVkIGRhdGUgZm9yIGRpc3BsYXkgaW4gdGhlIGlucHV0LlxyXG4gKiBEZWZhdWx0IHZhbHVlOiBGb3JtYXR0ZWQgcmVwcmVzZW50YXRpb24gb2YgdGhlIHNlbGVjdGVkIGRhdGUuXHJcbiovXHJcbmZvcm1hdHRlZERhdGU6IGFueSA7IFxyXG5cclxuIC8qKlxyXG4gKiBUcmFjayB0aGUgZWRpdGVkIGRhdGUgc2VwYXJhdGVseSB3aGVuIGluIGVkaXRpbmcgbW9kZS5cclxuICogRGVmYXVsdCB2YWx1ZTogQW4gZW1wdHkgc3RyaW5nLlxyXG4qL1xyXG5lZGl0ZWREYXRlOiBzdHJpbmcgPSAnJzsgXHJcblxyXG4vKipcclxuICogRmxhZyB0byBkZXRlcm1pbmUgaWYgdGhlIG1vbnRoIGRyb3Bkb3duIGlzIG9wZW4gb3IgY2xvc2VkLlxyXG4gKiBEZWZhdWx0IHZhbHVlOiB0cnVlIChvcGVuKS5cclxuKi9cclxuaXNNb250aERyb3Bkb3duT3BlbjogYm9vbGVhbiA9IHRydWU7IFxyXG5cclxuLyoqXHJcbiAqIEZsYWcgdG8gZGV0ZXJtaW5lIGlmIHRoZSB5ZWFyIGRyb3Bkb3duIGlzIG9wZW4gb3IgY2xvc2VkLlxyXG4gKiBEZWZhdWx0IHZhbHVlOiB0cnVlIChvcGVuKS5cclxuKi9cclxuaXNZZWFyRHJvcGRvd25PcGVuOiBib29sZWFuID0gdHJ1ZTsgXHJcblxyXG4vKipcclxuICogVGhlIHNlbGVjdGVkIG1vbnRoICgwLTExKS5cclxuICogRGVmYXVsdCB2YWx1ZTogVGhlIG1vbnRoIG9mIHRoZSBzZWxlY3RlZCBkYXRlLlxyXG4qL1xyXG5zZWxlY3RlZERhdGVNb250aDogbnVtYmVyID0gdGhpcy5zZWxlY3RlZERhdGUuZ2V0TW9udGgoKTsgXHJcblxyXG4vKipcclxuICogVGhlIHNlbGVjdGVkIHllYXIuXHJcbiAqIERlZmF1bHQgdmFsdWU6IFRoZSB5ZWFyIG9mIHRoZSBzZWxlY3RlZCBkYXRlLlxyXG4qL1xyXG5zZWxlY3RlZERhdGVZZWFyOiBudW1iZXIgPSB0aGlzLnNlbGVjdGVkRGF0ZS5nZXRGdWxsWWVhcigpOyBcclxuXHJcbiAvKipcclxuICogQW4gYXJyYXkgb2YgeWVhcnMgZm9yIHRoZSB5ZWFyIGRyb3Bkb3duLlxyXG4gKiBEZWZhdWx0IHZhbHVlOiBBbiBhcnJheSBvZiB5ZWFycyB3aXRoaW4gdGhlIHNwZWNpZmllZCByYW5nZS5cclxuKi9cclxueWVhcnM6IG51bWJlcltdIFxyXG5cclxuLyoqXHJcbiAqIFRoZSBsYW5ndWFnZS9sb2NhbGUgZm9yIHRoZSBkYXRlcGlja2VyLlxyXG4gKiBEZWZhdWx0IHZhbHVlOiAnZW4nIChFbmdsaXNoKS5cclxuICogQGV4YW1wbGVcclxuICogPG1lZmRldi1kYXRlcGlja2VyXHJcbiAqICAgW2xhbmddID0gXCIndWsnXCI+XHJcbiAqIDwvbWVmZGV2LWRhdGVwaWNrZXI+XHJcbiovXHJcbkBJbnB1dCgpIGxhbmc6IHN0cmluZyA9ICdlbic7IFxyXG5cclxuLyoqXHJcbiAqIFRoZSBkYXRlIGZvcm1hdCBmb3IgZGlzcGxheWluZyB0aGUgc2VsZWN0ZWQgZGF0ZS5cclxuICogRGVmYXVsdCB2YWx1ZTogJ0VFRSBNTU0gZGQgeXl5eScuXHJcbiAqIEBleGFtcGxlXHJcbiAqIDxtZWZkZXYtZGF0ZXBpY2tlclxyXG4gKiAgIFtkYXRlRm9ybWF0XT1cIidkZC9NTS95eXl5J1wiPlxyXG4gKiA8L21lZmRldi1kYXRlcGlja2VyPlxyXG4qL1xyXG5ASW5wdXQoKSBkYXRlRm9ybWF0OiBzdHJpbmcgPSAnRUVFIE1NTSBkZCB5eXl5JzsgXHJcblxyXG4vKipcclxuICogVGhlIHJhbmdlIG9mIHllYXJzIGF2YWlsYWJsZSBpbiB0aGUgeWVhciBkcm9wZG93bi5cclxuICogRGVmYXVsdCB2YWx1ZTogeyBzdGFydFllYXI6IDE5MDAsIHRvWWVhcjogMzAwIH0uXHJcbiAqIEBleGFtcGxlXHJcbiAqIDxtZWZkZXYtZGF0ZXBpY2tlclxyXG4gKiAgIFtyYW5nZV09XCJ7c3RhcnRZZWFyOiAxOTAwLCB0b1llYXI6IDMwMH1cIj5cclxuICogPC9tZWZkZXYtZGF0ZXBpY2tlcj5cclxuKi9cclxuQElucHV0KCdyYW5nZScpIHllYXJzUmFuZ2U6e3N0YXJ0WWVhcjpudW1iZXIsIHRvWWVhcjpudW1iZXJ9ID0ge3N0YXJ0WWVhcjoxOTAwLCB0b1llYXI6MzAwfTsgXHJcblxyXG4vKipcclxuICogV2hldGhlciB0aGUgZGF0ZXBpY2tlciBpcyBkaXNhYmxlZCBvciBub3QuXHJcbiAqIERlZmF1bHQgdmFsdWU6IGZhbHNlIChlbmFibGVkKS5cclxuICogQGV4YW1wbGVcclxuICogPG1lZmRldi1kYXRlcGlja2VyXHJcbiAqICAgW2Rpc2FibGVkXT1cImZhbHNlXCI+XHJcbiAqIDwvbWVmZGV2LWRhdGVwaWNrZXI+XHJcbiovXHJcbkBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuID0gZmFsc2U7IFxyXG5cclxuLyoqXHJcbiAqIFRoZSB0b3Agb2Zmc2V0IGZvciBwb3NpdGlvbmluZyB0aGUgZGF0ZXBpY2tlci5cclxuICogRGVmYXVsdCB2YWx1ZTogJzIwJy5cclxuICogQGV4YW1wbGVcclxuICogPG1lZmRldi1kYXRlcGlja2VyXHJcbiAqICAgW3RvcE9mZnNldF09XCInMjAnXCI+XHJcbiAqIDwvbWVmZGV2LWRhdGVwaWNrZXI+XHJcbiovXHJcbkBJbnB1dCgpIHRvcE9mZnNldDogc3RyaW5nID0gJzIwJztcclxuXHJcbi8qKlxyXG4gKiBUaGUgbGVmdCBvZmZzZXQgZm9yIHBvc2l0aW9uaW5nIHRoZSBkYXRlcGlja2VyLlxyXG4gKiBEZWZhdWx0IHZhbHVlOiAnMTAnLlxyXG4gKiBAZXhhbXBsZVxyXG4gKiA8bWVmZGV2LWRhdGVwaWNrZXJcclxuICogICBbbGVmdE9mZnNldF09XCInMTAnXCI+XHJcbiAqIDwvbWVmZGV2LWRhdGVwaWNrZXI+XHJcbiovXHJcbkBJbnB1dCgpIGxlZnRPZmZzZXQ6IHN0cmluZyA9ICcxMCc7IC8vRGVmYXVsdCB2YWx1ZVxyXG5cclxuLyoqXHJcbiAqIEV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgc2VsZWN0ZWQgZGF0ZSBpbiB0aGUgZGF0ZXBpY2tlciBjaGFuZ2VzLlxyXG4gKiBJdCBlbWl0cyBhIGBEYXRlYCBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBzZWxlY3RlZCBkYXRlLlxyXG4gKiBAZXhhbXBsZVxyXG4gKiA8bWVmZGV2LWRhdGVwaWNrZXJcclxuICogICAoZGF0ZUNoYW5nZWQpPVwib25EYXRlQ2hhbmdlZCgkZXZlbnQpXCI+XHJcbiAqIDwvbWVmZGV2LWRhdGVwaWNrZXI+XHJcbiovXHJcbkBPdXRwdXQoKSBkYXRlQ2hhbmdlZDogRXZlbnRFbWl0dGVyPERhdGU+ID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPigpO1xyXG5cclxuLyoqXHJcbiAqIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byB2YWxpZGF0ZSB1c2VyIGlucHV0IGZvciBkYXRlIGluIHRoZSBmb3JtYXQgXCJkZC9NTS95eXl5XCIuXHJcbiAqIC0gVGhlIGRheSAoZGQpIHNob3VsZCBiZSBiZXR3ZWVuIDAxIGFuZCAzMS5cclxuICogLSBUaGUgbW9udGggKE1NKSBzaG91bGQgYmUgYmV0d2VlbiAwMSBhbmQgMTIuXHJcbiAqIC0gVGhlIHllYXIgKHl5eXkpIHNob3VsZCBiZSBhIDQtZGlnaXQgbnVtYmVyLlxyXG4qL1xyXG4gIHByaXZhdGUgZGF0ZVJlZ0V4cDogUmVnRXhwID0gL14oMFsxLTldfFsxMl1bMC05XXwzWzAxXSlcXC8oMFsxLTldfDFbMC0yXSlcXC9cXGR7NH0kLztcclxuXHJcbi8qKlxyXG4gKiBUaGUgc3RyaW5nIGVudGVyZWQgYnkgdGhlIHVzZXIgZm9yIGRhdGUgaW5wdXQuXHJcbiAqIFRoaXMgdmFyaWFibGUgc3RvcmVzIHRoZSB1c2VyJ3MgaW5wdXQgYXMgdGhleSB0eXBlIGluIHRoZSBkYXRlIGZpZWxkLlxyXG4qL1xyXG4gIHVzZXJJbnB1dDogc3RyaW5nID0gJyc7XHJcbiAgXHJcbi8qKlxyXG4gKiBIb3N0IGxpc3RlbmVyIGZvciBkb2N1bWVudCBjbGljayBldmVudHMgdG8gaGFuZGxlIGNhbGVuZGFyIGludGVyYWN0aW9uLlxyXG4gKiBUaGlzIGZ1bmN0aW9uIGNoZWNrcyBpZiBhIGNsaWNrIGV2ZW50IG9jY3VycmVkIHdpdGhpbiB0aGUgY2FsZW5kYXIgb3IgaW5wdXQgZWxlbWVudHMuXHJcbiAqIC0gSWYgdGhlIGNsaWNrIG9jY3VycmVkIHdpdGhpbiB0aGUgY2FsZW5kYXIsIG5vIGFjdGlvbiBpcyB0YWtlbi5cclxuICogLSBJZiB0aGUgY2xpY2sgb2NjdXJyZWQgd2l0aGluIHRoZSBpbnB1dCBlbGVtZW50IGFuZCB0aGUgY29tcG9uZW50IGlzIG5vdCBpbiBlZGl0aW5nIG1vZGUsXHJcbiAqICAgaXQgb3BlbnMgdGhlIGNhbGVuZGFyLlxyXG4gKiAtIElmIHRoZSBjbGljayBvY2N1cnJlZCBvdXRzaWRlIHRoZSBjYWxlbmRhciBhbmQgaW5wdXQsIGl0IGNsb3NlcyB0aGUgY2FsZW5kYXIuXHJcbiAqIEBwYXJhbSBldmVudCBUaGUgTW91c2VFdmVudCBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBjbGljayBldmVudC5cclxuKi9cclxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjbGljaycsIFsnJGV2ZW50J10pXHJcbiAgb25DbGljayhldmVudDogTW91c2VFdmVudCkge1xyXG4gICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudDtcclxuICAgIGNvbnN0IGNhbGVuZGFyRWxlbWVudCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5jYWxlbmRhcicpO1xyXG4gICAgY29uc3QgaW5wdXRFbGVtZW50ID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXQnKTtcclxuXHJcbiAgICBpZiAoY2FsZW5kYXJFbGVtZW50ICYmIGNhbGVuZGFyRWxlbWVudC5jb250YWlucyh0YXJnZXRFbGVtZW50KSkge1xyXG4gICAgICAvLyDQmtC70ZbQuiDQstGW0LTQsdGD0LLRgdGPINC90LAg0LXQu9C10LzQtdC90YLRliDQutCw0LvQtdC90LTQsNGA0Y8sINC90ZbRh9C+0LPQviDQvdC1INGA0L7QsdC40LzQvlxyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGlucHV0RWxlbWVudCAmJiBpbnB1dEVsZW1lbnQuY29udGFpbnModGFyZ2V0RWxlbWVudCkgJiYgIXRoaXMuaXNFZGl0aW5nKSB7XHJcbiAgICAgIC8vINCa0LvRltC6INCy0ZbQtNCx0YPQstGB0Y8g0L3QsCDQtdC70LXQvNC10L3RgtGWIGlucHV0LCDQstGW0LTQutGA0LjQstCw0ZTQvNC+INC60LDQu9C10L3QtNCw0YBcclxuICAgICAgdGhpcy5pc0NhbGVuZGFyT3BlbiA9IHRydWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyDQmtC70ZbQuiDQstGW0LTQsdGD0LLRgdGPINC/0L7Qt9CwINC60LDQu9C10L3QtNCw0YDQtdC8INGC0LAgaW5wdXQsINC30LDQutGA0LjQstCw0ZTQvNC+INC60LDQu9C10L3QtNCw0YBcclxuICAgICAgdGhpcy5pc0NhbGVuZGFyT3BlbiA9IGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbi8qKlxyXG4gKiBDb25zdHJ1Y3RvciBmb3IgdGhlIERhdGVwaWNrZXJDb21wb25lbnQgY2xhc3MuXHJcbiAqIEBwYXJhbSBkYXRlUGlwZSBBIHNlcnZpY2UgZm9yIGZvcm1hdHRpbmcgYW5kIHBhcnNpbmcgZGF0ZXMuXHJcbiAqIEBwYXJhbSBlbGVtZW50UmVmIEEgcmVmZXJlbmNlIHRvIHRoZSBlbGVtZW50IG9uIHdoaWNoIHRoaXMgY29tcG9uZW50IGlzIGF0dGFjaGVkLlxyXG4gKiBJdCBpcyB1c2VkIHRvIGFjY2VzcyBET00gZWxlbWVudHMuXHJcbiovXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBkYXRlUGlwZTogRGF0ZVBpcGUsIHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xyXG4gICAgdGhpcy51cGRhdGVJbnB1dFZhbHVlKClcclxuICB9XHJcbiAgXHJcbi8qKlxyXG4gKiBMaWZlY3ljbGUgaG9vayBjYWxsZWQgYWZ0ZXIgdGhlIGNvbXBvbmVudCBpcyBpbml0aWFsaXplZC5cclxuICogSXQgaW5pdGlhbGl6ZXMgdGhlIHllYXJzIGZvciB0aGUgeWVhciBzZWxlY3QgZHJvcGRvd24uXHJcbiovXHJcbiAgbmdPbkluaXQoKXtcclxuICAgIHRoaXMuaW5pdGlhbGl6ZVllYXJzKCk7XHJcbiAgfVxyXG4vKipcclxuICogTGlmZWN5Y2xlIGhvb2sgY2FsbGVkIHdoZW5ldmVyIHRoZSBpbnB1dCBwcm9wZXJ0aWVzIG9mIHRoZSBjb21wb25lbnQgY2hhbmdlLlxyXG4gKiBJdCB1cGRhdGVzIHRoZSBpbnB1dCB2YWx1ZS5cclxuKi9cclxuICBuZ09uQ2hhbmdlcygpIHtcclxuICAgIHRoaXMudXBkYXRlSW5wdXRWYWx1ZSgpO1xyXG4gIH1cclxuXHJcbi8qKlxyXG4gKiBBbiBhcnJheSBvZiBtb250aCBuYW1lcyBiYXNlZCBvbiB0aGUgc2VsZWN0ZWQgbGFuZ3VhZ2UuXHJcbiAqIEl0IHByb3ZpZGVzIGxvY2FsaXplZCBtb250aCBuYW1lcyBmb3IgZGlzcGxheSBpbiB0aGUgZGF0ZXBpY2tlci5cclxuKi9cclxuICBwcml2YXRlIGdldCBtb250aHMoKXtcclxuICAgIHJldHVybiB0aGlzLmdldE1vbnRoTGlzdCh0aGlzLmxhbmcpO1xyXG4gIH0gIFxyXG5cclxuLyoqXHJcbiAqIEFuIGFycmF5IG9mIHdlZWtkYXkgbmFtZXMgYmFzZWQgb24gdGhlIHNlbGVjdGVkIGxhbmd1YWdlLlxyXG4gKiBJdCBwcm92aWRlcyBsb2NhbGl6ZWQgd2Vla2RheSBuYW1lcyBmb3IgZGlzcGxheSBpbiB0aGUgZGF0ZXBpY2tlci5cclxuKi9cclxuICBwcml2YXRlIGdldCB3ZWVrZGF5cygpIHtcclxuICAgIHJldHVybiB0aGlzLmdldFdlZWtkYXlMaXN0KHRoaXMubGFuZyk7XHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIEluaXRpYWxpemUgdGhlIGxpc3Qgb2YgeWVhcnMgdG8gYmUgZGlzcGxheWVkIGluIHRoZSB5ZWFyIGRyb3Bkb3duLlxyXG4gKiBUaGlzIG1ldGhvZCBwb3B1bGF0ZXMgdGhlICd5ZWFycycgYXJyYXkgd2l0aCBhIHJhbmdlIG9mIHllYXJzIGJhc2VkIG9uIHRoZSBwcm92aWRlZCAneWVhcnNSYW5nZScgY29uZmlndXJhdGlvbi5cclxuICogQGV4YW1wbGVcclxuICogYGBgXHJcbiAqIC8vIEFzc3VtaW5nICd5ZWFyc1JhbmdlJyBpcyB7IHN0YXJ0WWVhcjogMTkwMCwgdG9ZZWFyOiAzMDAgfVxyXG4gKiAvLyBBZnRlciBjYWxsaW5nIGluaXRpYWxpemVZZWFycygpLCAneWVhcnMnIG1pZ2h0IGNvbnRhaW4gWzE5MDAsIDE5MDEsIC4uLiwgMzAwXVxyXG4gKiB0aGlzLmluaXRpYWxpemVZZWFycygpO1xyXG4gKiBgYGBcclxuKi9cclxuICBwcml2YXRlIGluaXRpYWxpemVZZWFycygpIHtcclxuICAgIHRoaXMueWVhcnMgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiB0aGlzLnllYXJzUmFuZ2UudG9ZZWFyIH0sIChfLCBpbmRleCkgPT4gaW5kZXggKyB0aGlzLnllYXJzUmFuZ2Uuc3RhcnRZZWFyKTtcclxuICB9XHJcblxyXG4vKipcclxuICogVG9nZ2xlIHRoZSBlZGl0aW5nIG1vZGUgZm9yIHRoZSBkYXRlIGlucHV0LiBXaGVuIGVuYWJsZWQsIHRoZSB1c2VyIGNhbiBlZGl0IHRoZSBkYXRlIGRpcmVjdGx5IGluIHRoZSBpbnB1dCBmaWVsZC5cclxuICogVGhpcyBtZXRob2Qgc2V0cyB0aGUgJ2lzRWRpdGluZycgZmxhZyB0byB0cnVlIGFuZCBzdG9yZXMgdGhlIGN1cnJlbnQgZm9ybWF0dGVkIGRhdGUgZm9yIGVkaXRpbmcuXHJcbiovXHJcbiAgdG9nZ2xlRWRpdCgpIHtcclxuICAgIHRoaXMuaXNFZGl0aW5nID0gdHJ1ZTtcclxuICAgIHRoaXMuZWRpdGVkRGF0ZSA9IHRoaXMuZm9ybWF0U2VsZWN0ZWREYXRlKCk7IC8vIFN0b3JlIHRoZSBjdXJyZW50IGZvcm1hdHRlZCBkYXRlIGZvciBlZGl0aW5nXHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIEdldCBhIGxpc3Qgb2YgbW9udGggbmFtZXMgaW4gdGhlIHNwZWNpZmllZCBsYW5ndWFnZSBhbmQgZm9ybWF0LlxyXG4gKiBAcGFyYW0gbG9jYWxlcyAtIEFuIG9wdGlvbmFsIHBhcmFtZXRlciBzcGVjaWZ5aW5nIHRoZSBsb2NhbGUgb3IgbG9jYWxlcyB0byB1c2UgZm9yIGZvcm1hdHRpbmcuXHJcbiAqIEBwYXJhbSBmb3JtYXQgLSBUaGUgZm9ybWF0IGZvciBtb250aCBuYW1lcywgZWl0aGVyIFwibG9uZ1wiIChkZWZhdWx0KSBvciBcInNob3J0XCIuXHJcbiAqIEByZXR1cm5zIEFuIGFycmF5IG9mIG1vbnRoIG5hbWVzIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBmb3JtYXQgYW5kIGxvY2FsZS5cclxuICogYGBgXHJcbiAqIC8vIEdldCBhIGxpc3Qgb2YgbW9udGggbmFtZXMgaW4gdGhlIGRlZmF1bHQgbGFuZ3VhZ2UgYW5kIGxvbmcgZm9ybWF0XHJcbiAqIGNvbnN0IG1vbnRocyA9IHRoaXMuZ2V0TW9udGhMaXN0KHRoaXMubGFuZyk7XHJcbiAqIGBgYFxyXG4qL1xyXG4gIHByaXZhdGUgZ2V0TW9udGhMaXN0KCAgbG9jYWxlcz86IHN0cmluZyB8IHN0cmluZ1tdLCAgZm9ybWF0OiBcImxvbmdcIiB8IFwic2hvcnRcIiA9IFwibG9uZ1wiKTogc3RyaW5nW10geyAgXHJcbiAgICBjb25zdCB5ZWFyID0gbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpO1xyXG4gICAgY29uc3QgbW9udGhMaXN0ID0gWy4uLkFycmF5KDEyKS5rZXlzKCldO1xyXG4gICAgY29uc3QgZm9ybWF0dGVyID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQobG9jYWxlcywgeyAgICBtb250aDogZm9ybWF0ICB9KTtcclxuICAgIGNvbnN0IGdldE1vbnRoTmFtZSA9IChtb250aEluZGV4OiBudW1iZXIpID0+IGZvcm1hdHRlci5mb3JtYXQobmV3IERhdGUoeWVhciwgbW9udGhJbmRleCkpO1xyXG4gICAgIHJldHVybiBtb250aExpc3QubWFwKGdldE1vbnRoTmFtZSk7XHJcbiAgfVxyXG4gIFxyXG4vKipcclxuICogR2V0IGEgbGlzdCBvZiB3ZWVrZGF5IG5hbWVzIGluIHRoZSBzcGVjaWZpZWQgbGFuZ3VhZ2UgYW5kIGZvcm1hdC5cclxuICogQHBhcmFtIGxvY2FsZXMgLSBBbiBvcHRpb25hbCBwYXJhbWV0ZXIgc3BlY2lmeWluZyB0aGUgbG9jYWxlIG9yIGxvY2FsZXMgdG8gdXNlIGZvciBmb3JtYXR0aW5nLlxyXG4gKiBAcGFyYW0gZm9ybWF0IC0gVGhlIGZvcm1hdCBmb3Igd2Vla2RheSBuYW1lcywgZWl0aGVyIFwic2hvcnRcIiAoZGVmYXVsdCkgb3IgXCJsb25nXCIuXHJcbiAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHdlZWtkYXkgbmFtZXMgYmFzZWQgb24gdGhlIHByb3ZpZGVkIGZvcm1hdCBhbmQgbG9jYWxlLlxyXG4gKiBgYGBcclxuICogLy8gR2V0IGEgbGlzdCBvZiB3ZWVrZGF5IG5hbWVzIGluIHRoZSBkZWZhdWx0IGxhbmd1YWdlIGFuZCBzaG9ydCBmb3JtYXRcclxuICogY29uc3Qgd2Vla2RheXMgPSB0aGlzLmdldFdlZWtkYXlMaXN0KCk7XHJcbiAqIGBgYFxyXG4qL1xyXG4gIHByaXZhdGUgZ2V0V2Vla2RheUxpc3QobG9jYWxlcz86IHN0cmluZyB8IHN0cmluZ1tdLCBmb3JtYXQ6IFwic2hvcnRcIiB8IFwibG9uZ1wiID0gXCJzaG9ydFwiKTogc3RyaW5nW10ge1xyXG4gICAgICBjb25zdCB3ZWVrZGF5cyA9IFsuLi5BcnJheSg3KS5rZXlzKCldO1xyXG4gICAgICBjb25zdCBtb25kYXlJbmRleCA9IHdlZWtkYXlzLmluZGV4T2YoMCk7XHJcbiAgICAgIHdlZWtkYXlzLnNwbGljZShtb25kYXlJbmRleCwgMSk7IFxyXG4gICAgICB3ZWVrZGF5cy5wdXNoKDApOyBcclxuICAgICAgY29uc3QgZm9ybWF0dGVyID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQobG9jYWxlcywgeyB3ZWVrZGF5OiBmb3JtYXQgfSk7ICAgIFxyXG4gICAgICBjb25zdCBnZXRXZWVrZGF5TmFtZSA9ICh3ZWVrZGF5SW5kZXg6IG51bWJlcikgPT4ge1xyXG4gICAgICAgIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0KG5ldyBEYXRlKDIwMjMsIDksIHdlZWtkYXlJbmRleCArIDEpKTsgXHJcbiAgICAgIH07XHJcbiAgICAgIHJldHVybiB3ZWVrZGF5cy5tYXAoZ2V0V2Vla2RheU5hbWUpO1xyXG4gIH1cclxuICAgIFxyXG4gICAgXHJcbi8qKlxyXG4gKiBUb2dnbGUgdGhlIHZpc2liaWxpdHkgb2YgdGhlIGNhbGVuZGFyIGNvbXBvbmVudC4gV2hlbiBjYWxsZWQsIHRoaXMgbWV0aG9kIGNoYW5nZXMgdGhlICdpc0NhbGVuZGFyT3BlbicgZmxhZ1xyXG4gKiB0byBzaG93IG9yIGhpZGUgdGhlIGNhbGVuZGFyIGludGVyZmFjZS5cclxuICogYGBgXHJcbiAqIC8vIFRvZ2dsZSB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgY2FsZW5kYXJcclxuICogdGhpcy50b2dnbGVDYWxlbmRhcigpO1xyXG4gKiBgYGBcclxuKi9cclxuICBwcml2YXRlIHRvZ2dsZUNhbGVuZGFyKCkge1xyXG4gICAgIHRoaXMuaXNDYWxlbmRhck9wZW4gPSAhdGhpcy5pc0NhbGVuZGFyT3BlblxyXG4gIH1cclxuXHJcbi8qKlxyXG4gKiBTYXZlIHRoZSBlZGl0ZWQgZGF0ZSBpbnB1dCBieSB0aGUgdXNlciwgcHJvdmlkZWQgaXQgbWF0Y2hlcyB0aGUgc3BlY2lmaWVkIGRhdGUgZm9ybWF0LlxyXG4gKiBUaGlzIG1ldGhvZCBjaGVja3MgaWYgdGhlIGVudGVyZWQgZGF0ZSBpcyBpbiBhIHZhbGlkIGZvcm1hdCwgZGlzYWJsZXMgdGhlIGVkaXRpbmcgbW9kZSwgYW5kIGFwcGxpZXNcclxuICogdGhlIGVkaXRlZCBkYXRlIHRvIHRoZSAnc2VsZWN0ZWREYXRlJy4gSXQgdGhlbiByZWZvcm1hdHMgdGhlIHNlbGVjdGVkIGRhdGUgYW5kIGNsb3NlcyB0aGUgY2FsZW5kYXIuXHJcbiAqIGBgYFxyXG4gKiAvLyBTYXZlIHRoZSBlZGl0ZWQgZGF0ZSBhbmQgdXBkYXRlIHRoZSBzZWxlY3RlZCBkYXRlXHJcbiAqIHRoaXMuc2F2ZUVkaXRlZERhdGUoKTtcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSBzYXZlRWRpdGVkRGF0ZSgpIHtcclxuICAgIGlmICh0aGlzLmlzRGF0ZVZhbGlkKHRoaXMuZWRpdGVkRGF0ZSkpIHtcclxuICAgICAgdGhpcy5pc0VkaXRpbmcgPSBmYWxzZTsgXHJcbiAgICAgIGNvbnN0IFtkYXksIG1vbnRoLCB5ZWFyXSA9IHRoaXMuZWRpdGVkRGF0ZS5zcGxpdCgnLycpO1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IG5ldyBEYXRlKCt5ZWFyLCArbW9udGggLSAxLCArZGF5KTtcclxuICAgICAgdGhpcy5mb3JtYXREYXRlKCk7IFxyXG4gICAgICB0aGlzLnRvZ2dsZUNhbGVuZGFyKCk7IFxyXG4gICAgfSBcclxuICB9XHJcblxyXG4vKipcclxuICAqIEhhbmRsZSB1c2VyIGlucHV0IGluIHRoZSBlZGl0YWJsZSBpbnB1dCBmaWVsZCBmb3IgZGF0ZSBlZGl0aW5nLiBUaGlzIG1ldGhvZCBjYXB0dXJlcyB0aGUgaW5wdXQgdmFsdWVcclxuICAqIGFuZCBzdG9yZXMgaXQgaW4gdGhlICdlZGl0ZWREYXRlJyB2YXJpYWJsZS4gSWYgdGhlIGlucHV0IG1hdGNoZXMgdGhlIHZhbGlkIGRhdGUgZm9ybWF0LCBpdCB1cGRhdGVzXHJcbiAgKiAnc2VsZWN0ZWREYXRlTW9udGgnIGFuZCAnc2VsZWN0ZWREYXRlWWVhcicgYWNjb3JkaW5nbHkuXHJcbiAgKiBAcGFyYW0gZXZlbnQgLSBUaGUgaW5wdXQgZXZlbnQgY29udGFpbmluZyB0aGUgdXNlcidzIGlucHV0LlxyXG4gICogYGBgXHJcbiAgKiAvLyBIYW5kbGUgdXNlciBpbnB1dCBpbiB0aGUgZWRpdGFibGUgaW5wdXQgZmllbGRcclxuICAqIHRoaXMub25EYXRlSW5wdXQoZXZlbnQpO1xyXG4gICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSBvbkRhdGVJbnB1dChldmVudDogYW55KSB7XHJcbiAgICBjb25zdCBpbnB1dERhdGU6IHN0cmluZyA9IGV2ZW50LnRhcmdldC52YWx1ZTtcclxuICAgIGlmICh0aGlzLmlzRGF0ZVZhbGlkKGlucHV0RGF0ZSkpIHtcclxuICAgICAgdGhpcy5lZGl0ZWREYXRlID0gaW5wdXREYXRlO1xyXG4gICAgICBjb25zdCBwYXJzZWREYXRlID0gaW5wdXREYXRlLnNwbGl0KCcvJyk7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWREYXRlTW9udGggPSArcGFyc2VkRGF0ZVsxXSAtIDE7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWREYXRlWWVhciA9ICtwYXJzZWREYXRlWzJdO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbi8qKlxyXG4gKiBUb2dnbGUgdGhlIHZpc2liaWxpdHkgb2YgdGhlIG1vbnRoIGRyb3Bkb3duIGluIHRoZSBjYWxlbmRhciBpbnRlcmZhY2UuXHJcbiAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gb3BlbiBvciBjbG9zZSB0aGUgZHJvcGRvd24gZm9yIHNlbGVjdGluZyBtb250aHMuXHJcbiAqIEBwYXJhbSBldmVudCAtIFRoZSBldmVudCB0cmlnZ2VyaW5nIHRoZSB0b2dnbGUgYWN0aW9uIChlLmcuLCBhIGNsaWNrIGV2ZW50KS5cclxuICogYGBgXHJcbiAqIC8vIFRvZ2dsZSB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgbW9udGggZHJvcGRvd25cclxuICogdGhpcy50b2dnbGVNb250aERyb3Bkb3duKGV2ZW50KTtcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSB0b2dnbGVNb250aERyb3Bkb3duKGV2ZW50OiBFdmVudCkge1xyXG4gICAgdGhpcy5pc01vbnRoRHJvcGRvd25PcGVuID0gIXRoaXMuaXNNb250aERyb3Bkb3duT3BlbjtcclxuICB9XHJcblxyXG4vKipcclxuICAqIFRvZ2dsZSB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgeWVhciBkcm9wZG93biBpbiB0aGUgY2FsZW5kYXIgaW50ZXJmYWNlLlxyXG4gICogVGhpcyBtZXRob2QgaXMgdXNlZCB0byBvcGVuIG9yIGNsb3NlIHRoZSBkcm9wZG93biBmb3Igc2VsZWN0aW5nIHllYXJzLlxyXG4gICogQHBhcmFtIGV2ZW50IC0gVGhlIGV2ZW50IHRyaWdnZXJpbmcgdGhlIHRvZ2dsZSBhY3Rpb24gKGUuZy4sIGEgY2xpY2sgZXZlbnQpLlxyXG4gICogYGBgXHJcbiAgKiAvLyBUb2dnbGUgdGhlIHZpc2liaWxpdHkgb2YgdGhlIHllYXIgZHJvcGRvd25cclxuICAqIHRoaXMudG9nZ2xlWWVhckRyb3Bkb3duKGV2ZW50KTtcclxuICAqIGBgYFxyXG4qL1xyXG4gIHByaXZhdGUgdG9nZ2xlWWVhckRyb3Bkb3duKGV2ZW50OiBFdmVudCkge1xyXG4gICAgdGhpcy5pc1llYXJEcm9wZG93bk9wZW4gPSAhdGhpcy5pc1llYXJEcm9wZG93bk9wZW47XHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIEhhbmRsZSB0aGUgY2hhbmdlIG9mIHRoZSBzZWxlY3RlZCBtb250aCBpbiB0aGUgY2FsZW5kYXIgaW50ZXJmYWNlLlxyXG4gKiBUaGlzIG1ldGhvZCB1cGRhdGVzIHRoZSBpbnB1dCB2YWx1ZSwgc2V0cyB0aGUgc2VsZWN0ZWQgZGF0ZSB0byB0aGUgZmlyc3QgZGF5IG9mIHRoZSBjaG9zZW4gbW9udGgsXHJcbiAqIGFuZCByZWNhbGN1bGF0ZXMgdGhlIGNhbGVuZGFyIGRpc3BsYXkgYWNjb3JkaW5nbHkuXHJcbiAqIGBgYFxyXG4gKiAvLyBIYW5kbGUgdGhlIGNoYW5nZSBvZiB0aGUgc2VsZWN0ZWQgbW9udGhcclxuICogdGhpcy5vbk1vbnRoQ2hhbmdlKCk7XHJcbiAqIGBgYFxyXG4qL1xyXG4gIHByaXZhdGUgb25Nb250aENoYW5nZSgpIHtcclxuICAgIHRoaXMudXBkYXRlSW5wdXRWYWx1ZSgpO1xyXG4gICAgdGhpcy5zZWxlY3RlZERhdGUgPSBuZXcgRGF0ZSh0aGlzLnNlbGVjdGVkRGF0ZVllYXIsIHRoaXMuc2VsZWN0ZWREYXRlTW9udGgsIDEpO1xyXG4gICAgdGhpcy5jYWxjdWxhdGVGaXJzdERheU9mQ2FsZW5kYXIoKTtcclxuICB9XHJcblxyXG4vKipcclxuICogSGFuZGxlIHRoZSBjaGFuZ2Ugb2YgdGhlIHNlbGVjdGVkIHllYXIgaW4gdGhlIGNhbGVuZGFyIGludGVyZmFjZS5cclxuICogVGhpcyBtZXRob2QgdXBkYXRlcyB0aGUgaW5wdXQgdmFsdWUsIHNldHMgdGhlIHNlbGVjdGVkIGRhdGUgdG8gdGhlIGZpcnN0IGRheSBvZiB0aGUgY2hvc2VuIHllYXIsXHJcbiAqIHJlZm9ybWF0cyB0aGUgc2VsZWN0ZWQgZGF0ZSwgYW5kIHJlY2FsY3VsYXRlcyB0aGUgY2FsZW5kYXIgZGlzcGxheS5cclxuICogYGBgXHJcbiAqIC8vIEhhbmRsZSB0aGUgY2hhbmdlIG9mIHRoZSBzZWxlY3RlZCB5ZWFyXHJcbiAqIHRoaXMub25ZZWFyQ2hhbmdlKCk7XHJcbiAqIGBgYFxyXG4qL1xyXG4gIHByaXZhdGUgb25ZZWFyQ2hhbmdlKCkge1xyXG4gICAgdGhpcy51cGRhdGVJbnB1dFZhbHVlKCk7XHJcbiAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IG5ldyBEYXRlKHRoaXMuc2VsZWN0ZWREYXRlWWVhciwgdGhpcy5zZWxlY3RlZERhdGVNb250aCwgMSk7XHJcbiAgICB0aGlzLmZvcm1hdERhdGUoKTtcclxuICAgIHRoaXMuY2FsY3VsYXRlRmlyc3REYXlPZkNhbGVuZGFyKCk7XHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIFNlbGVjdCBhIGRhdGUgaW4gdGhlIGNhbGVuZGFyIGludGVyZmFjZSBhbmQgcGVyZm9ybSBuZWNlc3NhcnkgdXBkYXRlcy5cclxuICogVGhpcyBtZXRob2Qgc2V0cyB0aGUgc2VsZWN0ZWQgZGF0ZSwgZm9ybWF0cyBpdCwgY2xvc2VzIHRoZSBjYWxlbmRhciwgYW5kIGVtaXRzIGEgZGF0ZUNoYW5nZWQgZXZlbnQuXHJcbiAqIEl0IGFsc28gdXBkYXRlcyB0aGUgc2VsZWN0ZWQgbW9udGggYW5kIHllYXIgZHJvcGRvd24gdmFsdWVzLlxyXG4gKiBAcGFyYW0gZGF0ZSAtIFRoZSBkYXRlIHRvIGJlIHNlbGVjdGVkIGluIHRoZSBjYWxlbmRhci5cclxuKi9cclxuICBzZWxlY3REYXRlKGRhdGU6IERhdGUpIHtcclxuICB0aGlzLnNlbGVjdGVkRGF0ZSA9IGRhdGU7XHJcbiAgdGhpcy5mb3JtYXREYXRlKCk7XHJcbiAgdGhpcy5pc0NhbGVuZGFyT3BlbiA9IGZhbHNlO1xyXG4gIHRoaXMuZGF0ZUNoYW5nZWQubmV4dCh0aGlzLnNlbGVjdGVkRGF0ZSk7XHJcbiAgdGhpcy5zZWxlY3RlZERhdGVNb250aCA9IHRoaXMuc2VsZWN0ZWREYXRlLmdldE1vbnRoKCk7XHJcbiAgdGhpcy5zZWxlY3RlZERhdGVZZWFyID0gdGhpcy5zZWxlY3RlZERhdGUuZ2V0RnVsbFllYXIoKTtcclxuICB9XHJcblxyXG4vKipcclxuICogRm9ybWF0IHRoZSBzZWxlY3RlZCBkYXRlIGJhc2VkIG9uIHRoZSBjaG9zZW4gZGF0ZSBmb3JtYXQgYW5kIGxhbmd1YWdlLlxyXG4gKiBUaGlzIG1ldGhvZCB1c2VzIHRoZSBBbmd1bGFyIERhdGVQaXBlIHRvIGZvcm1hdCB0aGUgc2VsZWN0ZWQgZGF0ZSBhbmQgdXBkYXRlcyB0aGUgZm9ybWF0dGVkRGF0ZSB2YXJpYWJsZS5cclxuICogYGBgXHJcbiAqIC8vIEZvcm1hdCB0aGUgc2VsZWN0ZWQgZGF0ZVxyXG4gKiB0aGlzLmZvcm1hdERhdGUoKTtcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSBmb3JtYXREYXRlKCkge1xyXG4gICAgdGhpcy5mb3JtYXR0ZWREYXRlID0gdGhpcy5kYXRlUGlwZS50cmFuc2Zvcm0odGhpcy5zZWxlY3RlZERhdGUsIHRoaXMuZGF0ZUZvcm1hdCkgfHwgJyc7XHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIEZvcm1hdCB0aGUgc2VsZWN0ZWQgZGF0ZSBiYXNlZCBvbiB0aGUgY2hvc2VuIGRhdGUgZm9ybWF0LCBsYW5ndWFnZSwgYW5kIGxvY2FsZS5cclxuICogVGhpcyBtZXRob2QgdXNlcyB0aGUgQW5ndWxhciBEYXRlUGlwZSB0byBmb3JtYXQgdGhlIHNlbGVjdGVkIGRhdGUgd2l0aCB0aGUgc3BlY2lmaWVkIGxhbmd1YWdlIGFuZCB1cGRhdGVzIHRoZSBmb3JtYXR0ZWQgZGF0ZSBhcyBhIHN0cmluZy5cclxuICogQHJldHVybnMgQSBmb3JtYXR0ZWQgZGF0ZSBzdHJpbmcuXHJcbiAqIGBgYFxyXG4gKiAvLyBGb3JtYXQgdGhlIHNlbGVjdGVkIGRhdGUgd2l0aCBsYW5ndWFnZVxyXG4gKiBjb25zdCBmb3JtYXR0ZWQgPSB0aGlzLmZvcm1hdFNlbGVjdGVkRGF0ZSgpO1xyXG4gKiBgYGBcclxuKi9cclxuICBwcml2YXRlIGZvcm1hdFNlbGVjdGVkRGF0ZSgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHRoaXMuZGF0ZVBpcGUudHJhbnNmb3JtKHRoaXMuc2VsZWN0ZWREYXRlLCB0aGlzLmRhdGVGb3JtYXQsIHRoaXMubGFuZykgfHwgJyc7XHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIFVwZGF0ZSB0aGUgaW5wdXQgdmFsdWUgZGlzcGxheWVkIGluIHRoZSBjYWxlbmRhciBpbnRlcmZhY2UuXHJcbiAqIFRoaXMgbWV0aG9kIHVwZGF0ZXMgdGhlIGlucHV0IHZhbHVlIHRvIGVpdGhlciB0aGUgZWRpdGVkIGRhdGUgb3IgdGhlIGZvcm1hdHRlZCBzZWxlY3RlZCBkYXRlLFxyXG4gKiBkZXBlbmRpbmcgb24gd2hldGhlciB0aGUgdXNlciBpcyBpbiBlZGl0IG1vZGUgb3Igbm90LlxyXG4gKiBgYGBcclxuICogLy8gVXBkYXRlIHRoZSBpbnB1dCB2YWx1ZVxyXG4gKiB0aGlzLnVwZGF0ZUlucHV0VmFsdWUoKTtcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSB1cGRhdGVJbnB1dFZhbHVlKCkge1xyXG4gICAgdGhpcy5mb3JtYXR0ZWREYXRlID0gdGhpcy5pc0VkaXRpbmcgPyB0aGlzLmVkaXRlZERhdGUgOiB0aGlzLmZvcm1hdFNlbGVjdGVkRGF0ZSgpO1xyXG4gIH1cclxuXHJcbi8qKlxyXG4gKiBHZXQgYW4gYXJyYXkgb2YgYXJyYXlzIHJlcHJlc2VudGluZyB0aGUgZGF5cyBvZiB0aGUgY3VycmVudCBtb250aC5cclxuICogRWFjaCBzdWItYXJyYXkgY29udGFpbnMgdGhlIGRheSBkYXRhIGZvciBhIHdlZWssIGFuZCBlYWNoIGRheSBkYXRhIG9iamVjdCBpbmNsdWRlcyB0aGUgZGF0ZSBhbmQgd2hldGhlciBpdCBiZWxvbmdzIHRvIHRoZSBjdXJyZW50IG1vbnRoLlxyXG4gKiBAcmV0dXJucyBBbiBhcnJheSBvZiBhcnJheXMgcmVwcmVzZW50aW5nIHRoZSBkYXlzIG9mIHRoZSBjdXJyZW50IG1vbnRoLlxyXG4gKiBgYGBcclxuICogLy8gR2V0IGFuIGFycmF5IG9mIGFycmF5cyByZXByZXNlbnRpbmcgdGhlIGRheXMgb2YgdGhlIGN1cnJlbnQgbW9udGhcclxuICogY29uc3QgY2FsZW5kYXIgPSB0aGlzLmNhbGVuZGFyRGF5cztcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSBnZXQgY2FsZW5kYXJEYXlzKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuY2FsY3VsYXRlRmlyc3REYXlPZkNhbGVuZGFyKCk7XHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIEdldCB0aGUgZGF0ZSBvZiB0aGUgcHJldmlvdXMgbW9udGggdG8gZGlzcGxheSBpbiBlbXB0eSBjZWxscyBvZiB0aGUgY3VycmVudCBtb250aC5cclxuICogVGhpcyBtZXRob2QgcmV0dXJucyB0aGUgZGF0ZSBvZiB0aGUgcHJldmlvdXMgbW9udGggaWYgdGhlIHByb3ZpZGVkIGRhdGUgaXMgbm90IGluIHRoZSBjdXJyZW50IG1vbnRoLlxyXG4gKiBJZiB0aGUgcHJvdmlkZWQgZGF0ZSBpcyBpbiB0aGUgY3VycmVudCBtb250aCwgaXQgcmV0dXJucyB0aGUgZGF0ZSdzIGRheSBhcyBhIHN0cmluZy5cclxuICogQHBhcmFtIGRhdGUgLSBUaGUgZGF0ZSB0byBldmFsdWF0ZS5cclxuICogQHJldHVybnMgVGhlIGRhdGUgb2YgdGhlIHByZXZpb3VzIG1vbnRoIG9yIGEgZGF5IHN0cmluZy5cclxuICogYGBgXHJcbiAqIC8vIEdldCB0aGUgcHJldmlvdXMgbW9udGgncyBkYXRlIHRvIGRpc3BsYXkgaW4gZW1wdHkgY2VsbHNcclxuICogY29uc3QgcHJldmlvdXNNb250aERhdGUgPSB0aGlzLmdldFByZXZpb3VzTW9udGhEYXRlKG5ldyBEYXRlKDIwMjMsIDgsIDEpKTtcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSBnZXRQcmV2aW91c01vbnRoRGF0ZShkYXRlOiBEYXRlKTogYW55IHtcclxuICAgIGlmICghZGF0ZSkge1xyXG4gICAgICByZXR1cm4gJyc7XHJcbiAgICB9XHJcbiAgICBjb25zdCBjdXJyZW50RGF0ZSA9IG5ldyBEYXRlKCk7XHJcbiAgICBpZiAoZGF0ZS5nZXRNb250aCgpID09PSBjdXJyZW50RGF0ZS5nZXRNb250aCgpICYmIGRhdGUuZ2V0RnVsbFllYXIoKSA9PT0gY3VycmVudERhdGUuZ2V0RnVsbFllYXIoKSkge1xyXG4gICAgICByZXR1cm4gZGF0ZS5nZXREYXRlKCkudG9TdHJpbmcoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmRhdGVQaXBlLnRyYW5zZm9ybShkYXRlLCAnZGQnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4vKipcclxuICogTmF2aWdhdGUgdG8gdGhlIHByZXZpb3VzIG1vbnRoIGluIHRoZSBjYWxlbmRhciBpbnRlcmZhY2UuXHJcbiAqIFRoaXMgbWV0aG9kIHVwZGF0ZXMgdGhlIHNlbGVjdGVkRGF0ZSwgZm9ybWF0cyBpdCwgYW5kIHJlY2FsY3VsYXRlcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSBjYWxlbmRhci5cclxuICogYGBgXHJcbiAqIC8vIE5hdmlnYXRlIHRvIHRoZSBwcmV2aW91cyBtb250aFxyXG4gKiB0aGlzLmdldFByZXZpb3VzTW9udGgoKTtcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSBnZXRQcmV2aW91c01vbnRoKCkge1xyXG4gICAgY29uc3QgY3VycmVudE1vbnRoID0gdGhpcy5zZWxlY3RlZERhdGUuZ2V0TW9udGgoKTtcclxuICAgIHRoaXMuc2VsZWN0ZWREYXRlID0gbmV3IERhdGUodGhpcy5zZWxlY3RlZERhdGUuZ2V0RnVsbFllYXIoKSwgY3VycmVudE1vbnRoIC0gMSwgMSk7XHJcbiAgICB0aGlzLmZvcm1hdERhdGUoKTtcclxuICAgIHRoaXMuY2FsY3VsYXRlRmlyc3REYXlPZkNhbGVuZGFyKCk7XHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIE5hdmlnYXRlIHRvIHRoZSBuZXh0IG1vbnRoIGluIHRoZSBjYWxlbmRhciBpbnRlcmZhY2UuXHJcbiAqIFRoaXMgbWV0aG9kIHVwZGF0ZXMgdGhlIHNlbGVjdGVkRGF0ZSwgZm9ybWF0cyBpdCwgYW5kIHJlY2FsY3VsYXRlcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSBjYWxlbmRhci5cclxuICogYGBgXHJcbiAqIC8vIE5hdmlnYXRlIHRvIHRoZSBuZXh0IG1vbnRoXHJcbiAqIHRoaXMuZ2V0TmV4dE1vbnRoKCk7XHJcbiAqIGBgYFxyXG4qL1xyXG4gIHByaXZhdGUgZ2V0TmV4dE1vbnRoKCkge1xyXG4gICAgY29uc3QgY3VycmVudE1vbnRoID0gdGhpcy5zZWxlY3RlZERhdGUuZ2V0TW9udGgoKTtcclxuICAgIHRoaXMuc2VsZWN0ZWREYXRlID0gbmV3IERhdGUodGhpcy5zZWxlY3RlZERhdGUuZ2V0RnVsbFllYXIoKSwgY3VycmVudE1vbnRoICsgMSwgMSk7XHJcbiAgICB0aGlzLmZvcm1hdERhdGUoKTtcclxuICAgIHRoaXMuY2FsY3VsYXRlRmlyc3REYXlPZkNhbGVuZGFyKCk7XHJcbiAgfVxyXG5cclxuLyoqXHJcbiAqIEdldCB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSBnaXZlbiBtb250aCBvZiBhIHNwZWNpZmljIHllYXIuXHJcbiAqIEBwYXJhbSB5ZWFyIC0gVGhlIHllYXIgZm9yIHdoaWNoIHlvdSB3YW50IHRvIGRldGVybWluZSB0aGUgbnVtYmVyIG9mIGRheXMuXHJcbiAqIEBwYXJhbSBtb250aCAtIFRoZSBtb250aCAoMC1iYXNlZCBpbmRleCkgZm9yIHdoaWNoIHlvdSB3YW50IHRvIGRldGVybWluZSB0aGUgbnVtYmVyIG9mIGRheXMuXHJcbiAqIEByZXR1cm5zIFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGUgc3BlY2lmaWVkIG1vbnRoIG9mIHRoZSBnaXZlbiB5ZWFyLlxyXG4qL1xyXG4gIHByaXZhdGUgZGF5c0luTW9udGgoeWVhcjogbnVtYmVyLCBtb250aDogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBuZXcgRGF0ZSh5ZWFyLCBtb250aCArIDEsIDApLmdldERhdGUoKTtcclxuICB9XHJcblxyXG4vKipcclxuICogQ2FsY3VsYXRlIHRoZSBzdHJ1Y3R1cmUgb2YgZGF5cyBpbiBhIG1vbnRoIGZvciB0aGUgY2FsZW5kYXIgZGlzcGxheS5cclxuICogVGhpcyBtZXRob2QgZ2VuZXJhdGVzIGEgbWF0cml4IG9mIGRheSBkYXRhIG9iamVjdHMgcmVwcmVzZW50aW5nIHRoZSBkYXlzIGluIHRoZSBjYWxlbmRhci5cclxuICogRWFjaCBkYXkgZGF0YSBvYmplY3QgY29udGFpbnMgdGhlIGRhdGUgYW5kIHdoZXRoZXIgaXQgYmVsb25ncyB0byB0aGUgY3VycmVudCBtb250aC5cclxuICogQHJldHVybnMgQSBtYXRyaXggb2YgZGF5IGRhdGEgb2JqZWN0cyBmb3IgdGhlIGNhbGVuZGFyIGRpc3BsYXkuXHJcbiovXHJcbiAgcHJpdmF0ZSBjYWxjdWxhdGVGaXJzdERheU9mQ2FsZW5kYXIoKSB7XHJcbiAgICBjb25zdCB5ZWFyID0gdGhpcy5zZWxlY3RlZERhdGUuZ2V0RnVsbFllYXIoKTtcclxuICAgIGNvbnN0IG1vbnRoID0gdGhpcy5zZWxlY3RlZERhdGUuZ2V0TW9udGgoKTtcclxuICAgIGNvbnN0IGZpcnN0RGF5T2ZNb250aCA9IG5ldyBEYXRlKHllYXIsIG1vbnRoLCAxKTtcclxuICAgIGNvbnN0IGZpcnN0V2Vla2RheSA9IGZpcnN0RGF5T2ZNb250aC5nZXREYXkoKTtcclxuICAgIGNvbnN0IHN0YXJ0RGF5ID0gZmlyc3RXZWVrZGF5ID09PSAwID8gLTUgOiAyIC0gZmlyc3RXZWVrZGF5O1xyXG4gICAgY29uc3QgY2FsZW5kYXJEYXlzID0gW107XHJcbiAgICBsZXQgY3VycmVudERheSA9IHN0YXJ0RGF5O1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCA2OyBpKyspIHtcclxuICAgICAgY29uc3Qgd2VlayA9IFtdO1xyXG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDc7IGorKykge1xyXG4gICAgICAgIGNvbnN0IGRheSA9IG5ldyBEYXRlKHllYXIsIG1vbnRoLCBjdXJyZW50RGF5KTtcclxuICAgICAgICBjb25zdCBkYXlEYXRhID0ge1xyXG4gICAgICAgICAgZGF0ZTogZGF5LFxyXG4gICAgICAgICAgaXNDdXJyZW50TW9udGg6IGN1cnJlbnREYXkgPj0gMSAmJiBjdXJyZW50RGF5IDw9IHRoaXMuZGF5c0luTW9udGgoeWVhciwgbW9udGgpLFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgd2Vlay5wdXNoKGRheURhdGEpO1xyXG4gICAgICAgIGN1cnJlbnREYXkrKztcclxuICAgICAgfVxyXG4gICAgICBjYWxlbmRhckRheXMucHVzaCh3ZWVrKTtcclxuICAgIH1cclxuICAgIHJldHVybiBjYWxlbmRhckRheXM7XHJcbiAgfVxyXG4gIFxyXG4vKipcclxuICogQ2hlY2sgaWYgYSBnaXZlbiBkYXRlIGlzIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgZGF0ZSBpbiB0aGUgY2FsZW5kYXIuXHJcbiAqIEBwYXJhbSBkYXRlIC0gVGhlIGRhdGUgdG8gY2hlY2suXHJcbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvdmlkZWQgZGF0ZSBtYXRjaGVzIHRoZSBzZWxlY3RlZCBkYXRlLCBvdGhlcndpc2UgYGZhbHNlYC5cclxuICogYGBgXHJcbiAqIC8vIENoZWNrIGlmIGEgZGF0ZSBpcyBzZWxlY3RlZFxyXG4gKiBjb25zdCBpc1NlbGVjdGVkID0gdGhpcy5pc0RhdGVTZWxlY3RlZChzb21lRGF0ZSk7XHJcbiAqIGBgYFxyXG4qL1xyXG4gIHByaXZhdGUgaXNEYXRlU2VsZWN0ZWQoZGF0ZTogRGF0ZSkge1xyXG4gICAgcmV0dXJuIGRhdGUudG9EYXRlU3RyaW5nKCkgPT09IHRoaXMuc2VsZWN0ZWREYXRlLnRvRGF0ZVN0cmluZygpO1xyXG4gIH1cclxuXHJcbi8qKlxyXG4gKiBDaGVjayBpZiBhIGRhdGUgc3RyaW5nIGlzIHZhbGlkIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgZGF0ZSBmb3JtYXQuXHJcbiAqIEBwYXJhbSBpbnB1dERhdGUgLSBUaGUgZGF0ZSBzdHJpbmcgdG8gdmFsaWRhdGUuXHJcbiAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgaW5wdXQgZGF0ZSBzdHJpbmcgaXMgdmFsaWQsIG90aGVyd2lzZSBgZmFsc2VgLlxyXG4gKiBgYGBcclxuICogLy8gQ2hlY2sgaWYgYSBkYXRlIHN0cmluZyBpcyB2YWxpZFxyXG4gKiBjb25zdCBpc1ZhbGlkRGF0ZSA9IHRoaXMuaXNEYXRlVmFsaWQoJzA1LzI1LzIwMjMnKTtcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSBpc0RhdGVWYWxpZChpbnB1dERhdGU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZGF0ZVJlZ0V4cC50ZXN0KGlucHV0RGF0ZSk7XHJcbiAgfVxyXG4gIFxyXG4vKipcclxuICogQ2hlY2sgaWYgYSBnaXZlbiBkYXRlIGlzIHRvZGF5J3MgZGF0ZS5cclxuICogQHBhcmFtIGRhdGUgLSBUaGUgZGF0ZSB0byBjaGVjay5cclxuICogQHJldHVybnMgYHRydWVgIGlmIHRoZSBwcm92aWRlZCBkYXRlIGlzIHRvZGF5J3MgZGF0ZSwgb3RoZXJ3aXNlIGBmYWxzZWAuXHJcbiAqIGBgYFxyXG4gKiAvLyBDaGVjayBpZiBhIGRhdGUgaXMgdG9kYXkncyBkYXRlXHJcbiAqIGNvbnN0IGlzVG9kYXkgPSB0aGlzLmlzRGF0ZVRvZGF5KHNvbWVEYXRlKTtcclxuICogYGBgXHJcbiovXHJcbiAgcHJpdmF0ZSBpc0RhdGVUb2RheShkYXRlOiBEYXRlKSB7XHJcbiAgICBjb25zdCB0b2RheSA9IG5ldyBEYXRlKCk7XHJcbiAgICByZXR1cm4gZGF0ZS50b0RhdGVTdHJpbmcoKSA9PT0gdG9kYXkudG9EYXRlU3RyaW5nKCk7XHJcbiAgfVxyXG59IiwiPGRpdiBjbGFzcz1cImRhdGVwaWNrZXItY29udGFpbmVyXCJcclxuW2NsYXNzLmRpc2FibGVkXT1cImRpc2FibGVkXCJcclxuPlxyXG5cclxuICA8IS0tIElucHV0LCBzYXZlICYgZWRpdCBidXR0b25zIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImlucHV0LWNvbnRhaW5lclwiPlxyXG5cclxuICAgICAgPGRpdiAqbmdJZj1cIiFpc0VkaXRpbmdcIj5cclxuXHJcbiAgICAgICAgPGlucHV0XHJcbiAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgIChjbGljayk9XCJ0b2dnbGVDYWxlbmRhcigpXCJcclxuICAgICAgICBbdmFsdWVdPVwiZm9ybWF0dGVkRGF0ZVwiXHJcbiAgICAgICAgW3JlYWRPbmx5XT1cInRydWVcIlxyXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0VkaXRpbmdcIlxyXG4gICAgICA+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwhLS0gRWRpdCAtLT5cclxuICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXBlbmNpbC1zcXVhcmUtbyBlZGl0LWJ1dHRvblwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiIChjbGljayk9XCJ0b2dnbGVFZGl0KClcIj48L2k+IFxyXG5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwiaXNFZGl0aW5nXCI+XHJcbiAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXHJcbiAgICAgICAgICAgIFt2YWx1ZV09XCJlZGl0ZWREYXRlXCJcclxuICAgICAgICAgICAgKGlucHV0KT1cIm9uRGF0ZUlucHV0KCRldmVudClcIlxyXG4gICAgICAgICAgICBjbGFzcz1cImJvcmRlci0zXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cInRvZ2dsZUNhbGVuZGFyKClcIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtZmxvcHB5LW8gZWRpdC1idXR0b25cIiAoY2xpY2spPVwic2F2ZUVkaXRlZERhdGUoKVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cclxuICAgICA8L2Rpdj4gICAgIFxyXG4gICAgPC9kaXY+XHJcblxyXG48IS0tIENhbGVuZGFyKERyb3Bkb3ducywgZGF0ZXMpIC0tPlxyXG4gIDxkaXYgKm5nSWY9XCJpc0NhbGVuZGFyT3BlblwiIGNsYXNzPVwiY2FsZW5kYXJcIiAjY2FsZW5kYXJDb250YWluZXIgXHJcbiAgW3N0eWxlLnRvcF09XCJ0b3BPZmZzZXRcIlxyXG4gIFtzdHlsZS5sZWZ0XT1cImxlZnRPZmZzZXRcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjYWxlbmRhci1oZWFkZXJcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibW9udGhCdXR0b25Db250YWluZXJcIj5cclxuICAgICAgICAgICAgPCEtLSBNb250aCBkcm9wZG93biAtLT5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlzTW9udGhEcm9wZG93bk9wZW47IGVsc2UgbW9udGhMYWJlbFwiPlxyXG4gICAgICAgICAgICAgIDxtZWZkZXYtc2VsZWN0ICAgIFxyXG4gICAgICAgICAgICAgIGNsYXNzPVwibW9udGhEcm9wZG93blwiXHJcbiAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJzZWxlY3RlZERhdGVNb250aFwiIFxyXG4gICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uTW9udGhDaGFuZ2UoKVwiXHJcbiAgICAgICAgICAgICAgW1BsYWNlSG9sZGVyXT1cIidtb250aCdcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtZWZkZXYtb3B0aW9uIFxyXG4gICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IG1vbnRoIG9mIG1vbnRoczsgbGV0IGkgPSBpbmRleFwiIFxyXG4gICAgICAgICAgICAgICAgW1ZhbHVlXT1cImlcIlxyXG4gICAgICAgICAgICAgICAgW0xhYmVsXSA9IFwibW9udGhcIiBcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgPnt7IG1vbnRoIH19PC9tZWZkZXYtb3B0aW9uPlxyXG4gICAgICAgICAgICAgIDwvbWVmZGV2LXNlbGVjdD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjbW9udGhMYWJlbD5cclxuICAgICAgICAgICAgICA8c3BhbiAoY2xpY2spPVwidG9nZ2xlTW9udGhEcm9wZG93bigkZXZlbnQpXCI+PC9zcGFuPlxyXG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG5cclxuICAgICAgICAgICAgPCEtLSBZZWFyIGRyb3Bkb3duIC0tPlxyXG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXNZZWFyRHJvcGRvd25PcGVuOyBlbHNlIHllYXJMYWJlbFwiPlxyXG4gICAgICAgICAgICAgIDxtZWZkZXYtc2VsZWN0IFxyXG4gICAgICAgICAgICAgIGNsYXNzPVwieWVhckRyb3Bkb3duXCIgXHJcbiAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJzZWxlY3RlZERhdGVZZWFyXCIgXHJcbiAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25ZZWFyQ2hhbmdlKClcIlxyXG4gICAgICAgICAgICAgIFtQbGFjZUhvbGRlcl09XCIneWVhcidcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgPG1lZmRldi1vcHRpb24gXHJcbiAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCB5ZWFyIG9mIHllYXJzXCIgXHJcbiAgICAgICAgICAgICAgICAgIFtMYWJlbF0gPSBcInllYXJcIiBcclxuICAgICAgICAgICAgICAgICAgW1ZhbHVlXT1cInllYXJcIiBcclxuICAgICAgICAgICAgICAgICAgPnt7eWVhcn19PC9tZWZkZXYtb3B0aW9uPlxyXG4gICAgICAgICAgICAgIDwvbWVmZGV2LXNlbGVjdD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjeWVhckxhYmVsPlxyXG4gICAgICAgICAgICAgIDxzcGFuIChjbGljayk9XCJ0b2dnbGVZZWFyRHJvcGRvd24oJGV2ZW50KVwiPnt7IHNlbGVjdGVkRGF0ZVllYXIgfX08L3NwYW4+XHJcbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgPCEtLSBDYWxlbmRhciBleGl0IGJ1dHRvbiAtLT5cclxuICAgICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXRpbWVzIHRvZ2dsZUNhbGVuZGFyQnV0dG9uXCIgKGNsaWNrKT1cInRvZ2dsZUNhbGVuZGFyKClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgICBcclxuICAgIDxkaXYgY2xhc3M9XCJjYWxlbmRhci1ib2R5XCI+XHJcbiAgICAgIDx0YWJsZT5cclxuICAgICAgICA8dHI+XHJcbiAgICAgICAgICA8dGggY2xhc3M9XCJhbGlnbi1pdGVtcy1jZW50ZXJcIiAqbmdGb3I9XCJsZXQgd2Vla2RheSBvZiB3ZWVrZGF5c1wiPnt7IHdlZWtkYXkgfX08L3RoPlxyXG4gICAgICAgIDwvdHI+XHJcbiAgICAgICAgPHRyICpuZ0Zvcj1cImxldCB3ZWVrIG9mIGNhbGVuZGFyRGF5c1wiPlxyXG4gICAgICAgICAgPHRkICpuZ0Zvcj1cImxldCBkYXlEYXRhIG9mIHdlZWtcIiBcclxuICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0RGF0ZShkYXlEYXRhLmRhdGUpXCJcclxuICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7ICdzZWxlY3RlZCc6IGlzRGF0ZVNlbGVjdGVkKGRheURhdGEuZGF0ZSksICdwcmV2LW1vbnRoJzogIWRheURhdGEuaXNDdXJyZW50TW9udGggfVwiPlxyXG5cclxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJkYXRlXCIgXHJcbiAgICAgICAgICAgICAgW2NsYXNzLnByZXYtbW9udGhdPVwiIWRheURhdGEuaXNDdXJyZW50TW9udGhcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICB7eyBkYXlEYXRhLmRhdGUuZ2V0RGF0ZSgpIH19XHJcbiAgICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgPC90cj5cclxuICAgICAgPC90YWJsZT5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG48L2Rpdj5cclxuXHJcbiJdfQ==
|