@hxui/angular
Version:
This README includes the steps that are necessary to import the HxUi-angular into a project or to contribute with development.
370 lines (369 loc) • 33.3 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import { Component, Input, Output, ElementRef, HostListener, EventEmitter, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
export class DatepickerFormComponent {
/**
* @param {?} element
*/
constructor(element) {
this.element = element;
this.disabled = false;
this.readonly = false;
this.required = false;
this.defaultToPresentDate = true;
this.allowPreviousDates = true;
this.allowFutureDates = true;
this.dateFormat = "dd/MM/y";
this.placeholder = "Date";
this.align = "bottom";
this.from = '';
this.to = '';
this.onDateChange = new EventEmitter();
this.visible = false;
this.dateValidators = new Array();
this.onChanged = new Array();
this.onTouched = new Array();
}
/**
* @return {?}
*/
ngOnInit() {
const /** @type {?} */ date = new Date();
this.presentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
if (this.defaultToPresentDate) {
setTimeout(() => {
this.setDate(this.presentDate);
});
}
// Close to the minimum and maxium possible dates, but still normalisable
// http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1
const /** @type {?} */ from = this.parseDate(this.from) || new Date(-8630000000000000);
const /** @type {?} */ to = this.parseDate(this.to) || new Date(8630000000000000);
if (!!this.from || !!this.to) {
this.validateDateRange = this.createDateRangeValidator(from, to);
this.dateValidators.push(this.validateDateRange.bind(this));
}
if (!this.allowPreviousDates)
this.dateValidators.push(this.validateIsNotBeforeDate.bind(this));
if (!this.allowFutureDates)
this.dateValidators.push(this.validateIsNotAfterDate.bind(this));
}
/**
* @param {?} date
* @return {?}
*/
setDate(date) {
this.date = date;
this.onDateChange.emit(date);
this.propogateChange(date);
}
/**
* @return {?}
*/
setVisible() {
this.visible = true;
}
/**
* @return {?}
*/
unsetVisible() {
this.visible = false;
}
/**
* @param {?} targetElement
* @return {?}
*/
onClickOutsideComponent(targetElement) {
if (!this.element.nativeElement.firstChild.contains(targetElement)) {
this.unsetVisible();
}
}
/**
* @param {?} inputDate
* @return {?}
*/
onDateSelectEvent(inputDate) {
this.unsetVisible();
this.setDate(inputDate);
}
/**
* @param {?} inputDate
* @return {?}
*/
onChange(inputDate) {
const /** @type {?} */ date = this.parseDate(inputDate);
if (inputDate == "") {
this.setDate(null);
}
else if (!!date) {
this.setDate(date);
}
else {
this.propogateChange(inputDate);
}
}
/**
* @return {?}
*/
onFocus() {
this.setVisible();
this.propogateTouched();
}
/**
* @param {?} inputDate
* @return {?}
*/
onTab(inputDate) {
this.onChange(inputDate);
this.unsetVisible();
this.propogateTouched();
}
/**
* @param {?} inputDate
* @return {?}
*/
parseDate(inputDate) {
// Since Date.Parse() only acceps m/d/y dates, we have to swap the day and month
let /** @type {?} */ dateArray = inputDate.split(/[.,\/ -]/);
if (dateArray.length == 3 && dateArray[2].length != 0) {
let /** @type {?} */ day = dateArray.shift();
dateArray.splice(1, 0, day);
let /** @type {?} */ parseInput = Date.parse(dateArray.join("/"));
if (!isNaN(parseInput)) {
return new Date(parseInput);
}
}
return null;
}
/**
* @param {?} date
* @return {?}
*/
validateIsNotBeforeDate(date) {
const /** @type {?} */ normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return normalisedDate.getTime() < this.presentDate.getTime();
}
/**
* @param {?} date
* @return {?}
*/
validateIsNotAfterDate(date) {
const /** @type {?} */ normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return normalisedDate.getTime() > this.presentDate.getTime();
}
/**
* @param {?} from
* @param {?} to
* @return {?}
*/
createDateRangeValidator(from, to) {
const /** @type {?} */ normalisedFromDate = new Date(from.getFullYear(), from.getMonth(), from.getDate());
const /** @type {?} */ normalisedToDate = new Date(to.getFullYear(), to.getMonth(), to.getDate());
return (date) => {
const /** @type {?} */ normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return !(normalisedFromDate.getTime() <= normalisedDate.getTime() &&
normalisedDate.getTime() <= normalisedToDate.getTime());
};
}
/**
* @param {?} value
* @return {?}
*/
writeValue(value) {
this.setDate(value);
}
/**
* @param {?} fn
* @return {?}
*/
registerOnChange(fn) {
this.onChanged.push(fn);
}
/**
* @param {?} fn
* @return {?}
*/
registerOnTouched(fn) {
this.onTouched.push(fn);
}
/**
* @return {?}
*/
propogateTouched() {
this.onTouched.forEach(fn => fn());
}
/**
* @param {?} value
* @return {?}
*/
propogateChange(value) {
this.onChanged.forEach(fn => fn(value));
}
/**
* @param {?} control
* @return {?}
*/
validate(control) {
const /** @type {?} */ date = Date.parse(control.value);
if (!this.required && (control.value === null || control.value === undefined)) {
this.isValid = true;
return null;
}
if (isNaN(date)) {
this.isValid = false;
return {
dateParseError: {
valid: false
}
};
}
if (!this.allowPreviousDates && this.validateIsNotBeforeDate(this.date)) {
this.isValid = false;
return {
previousDateError: {
valid: false
}
};
}
if (!this.allowFutureDates && this.validateIsNotAfterDate(this.date)) {
this.isValid = false;
return {
futureDateError: {
valid: false
}
};
}
if (this.validateDateRange && this.validateDateRange(this.date)) {
this.isValid = false;
return {
dateRangeError: {
valid: false
}
};
}
if (this.required && !this.date) {
this.isValid = false;
return {
dateRequiredError: {
valid: false
}
};
}
this.isValid = true;
return null;
}
}
DatepickerFormComponent.decorators = [
{ type: Component, args: [{
selector: 'hxa-datepicker-input, hxa-datepicker-form',
template: `<div class="hx-input-group hxa-datepicker-form">
<div class="hx-input-control" [ngClass]="{'is-danger': !isValid && datePickerForm.touched}">
<input class="hx-input" type="text" #datePickerForm="ngModel"
[required]="required ? true : null"
[disabled]="disabled"
[readonly]="readonly ? true : null"
[ngModel]="date | date:dateFormat"
(change)="onChange(datePickerForm.value)"
(focus)="onFocus()"
(keydown.Tab)="onTab(datePickerForm.value)">
<label class="hx-label" *ngIf="placeholder">{{placeholder}} <sup *ngIf="required">*</sup></label>
<div class="hx-help"></div>
<div class="hxa-datepicker-help">Please select a date</div>
</div>
<i class="hx-icon icon-calendar"></i>
<hxa-datepicker class="hxa-datepicker-calendar" *ngIf="visible"
[selectedDate]="date"
[validators]="dateValidators"
(onDateSelected)="onDateSelectEvent($event)"
[ngClass]="{'hxa-datepicker-calendar-top': align == 'top', 'hxa-datepicker-calendar-bottom': align == 'bottom'}"></hxa-datepicker>
</div>
`,
styles: [`.hxa-datepicker-form{position:relative;max-width:21rem}.hxa-datepicker-calendar{position:absolute;z-index:99;left:0}.hxa-datepicker-calendar-top{bottom:100%}.hxa-datepicker-calendar-bottom{top:70%}.hxa-datepicker-help{font-size:.75rem;margin-top:.25rem;color:#63605f}.hxa-datepicker-form input[readonly]~.hx-label{top:-.5rem;font-size:.75rem;color:#41b987}`],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DatepickerFormComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => DatepickerFormComponent),
multi: true,
}]
},] },
];
/** @nocollapse */
DatepickerFormComponent.ctorParameters = () => [
{ type: ElementRef, },
];
DatepickerFormComponent.propDecorators = {
"disabled": [{ type: Input },],
"readonly": [{ type: Input },],
"required": [{ type: Input },],
"defaultToPresentDate": [{ type: Input },],
"allowPreviousDates": [{ type: Input },],
"allowFutureDates": [{ type: Input },],
"dateFormat": [{ type: Input },],
"placeholder": [{ type: Input },],
"align": [{ type: Input },],
"from": [{ type: Input },],
"to": [{ type: Input },],
"onDateChange": [{ type: Output },],
"onClickOutsideComponent": [{ type: HostListener, args: ['document:click', ['$event.target'],] },],
};
function DatepickerFormComponent_tsickle_Closure_declarations() {
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
DatepickerFormComponent.decorators;
/**
* @nocollapse
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
*/
DatepickerFormComponent.ctorParameters;
/** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */
DatepickerFormComponent.propDecorators;
/** @type {?} */
DatepickerFormComponent.prototype.disabled;
/** @type {?} */
DatepickerFormComponent.prototype.readonly;
/** @type {?} */
DatepickerFormComponent.prototype.required;
/** @type {?} */
DatepickerFormComponent.prototype.defaultToPresentDate;
/** @type {?} */
DatepickerFormComponent.prototype.allowPreviousDates;
/** @type {?} */
DatepickerFormComponent.prototype.allowFutureDates;
/** @type {?} */
DatepickerFormComponent.prototype.dateFormat;
/** @type {?} */
DatepickerFormComponent.prototype.placeholder;
/** @type {?} */
DatepickerFormComponent.prototype.align;
/** @type {?} */
DatepickerFormComponent.prototype.from;
/** @type {?} */
DatepickerFormComponent.prototype.to;
/** @type {?} */
DatepickerFormComponent.prototype.onDateChange;
/** @type {?} */
DatepickerFormComponent.prototype.date;
/** @type {?} */
DatepickerFormComponent.prototype.visible;
/** @type {?} */
DatepickerFormComponent.prototype.presentDate;
/** @type {?} */
DatepickerFormComponent.prototype.isValid;
/** @type {?} */
DatepickerFormComponent.prototype.dateValidators;
/** @type {?} */
DatepickerFormComponent.prototype.onChanged;
/** @type {?} */
DatepickerFormComponent.prototype.onTouched;
/** @type {?} */
DatepickerFormComponent.prototype.validateDateRange;
/** @type {?} */
DatepickerFormComponent.prototype.element;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BoeHVpL2FuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZGF0ZXBpY2tlci9kYXRlcGlja2VyLWZvcm0uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQVUsVUFBVSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3JILE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxhQUFhLEVBQW9ELE1BQU0sZ0JBQWdCLENBQUM7QUFzQ3BILE1BQU07Ozs7SUF5QkosWUFBb0IsT0FBbUI7UUFBbkIsWUFBTyxHQUFQLE9BQU8sQ0FBWTt3QkF4Qm5CLEtBQUs7d0JBQ0wsS0FBSzt3QkFDTCxLQUFLO29DQUNPLElBQUk7a0NBQ04sSUFBSTtnQ0FDTixJQUFJOzBCQUNWLFNBQVM7MkJBQ1IsTUFBTTtxQkFDTSxRQUFRO29CQUMzQixFQUFFO2tCQUNKLEVBQUU7NEJBRTZCLElBQUksWUFBWSxFQUFRO3VCQUczQyxLQUFLOzhCQUdQLElBQUksS0FBSyxFQUEyQjt5QkFDeEMsSUFBSSxLQUFLLEVBQXlCO3lCQUNsQyxJQUFJLEtBQUssRUFBYztLQUlDOzs7O0lBRTVDLFFBQVE7UUFDTix1QkFBTSxJQUFJLEdBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFFakYsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQztZQUM5QixVQUFVLENBQUMsR0FBRyxFQUFFO2dCQUNkLElBQUksQ0FBQyxPQUFPLENBQUMsSUFB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O3dCQUN0RCxLQUFLLEVBQUUsSUFBSTtxQkFDWjtvQkFDRDt3QkFDRSxPQUFPLEVBQUUsYUFBYTt3QkFDdEIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQzt3QkFDdEQsS0FBSyxFQUFFLElBQUk7cUJBQ1osQ0FBQzthQUNIOzs7O1lBdEMwQyxVQUFVOzs7eUJBd0NsRCxLQUFLO3lCQUNMLEtBQUs7eUJBQ0wsS0FBSztxQ0FDTCxLQUFLO21DQUNMLEtBQUs7aUNBQ0wsS0FBSzsyQkFDTCxLQUFLOzRCQUNMLEtBQUs7c0JBQ0wsS0FBSztxQkFDTCxLQUFLO21CQUNMLEtBQUs7NkJBRUwsTUFBTTt3Q0FzRE4sWUFBWSxTQUFDLGdCQUFnQixFQUFFLENBQUMsZUFBZSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBPbkluaXQsIEVsZW1lbnRSZWYsIEhvc3RMaXN0ZW5lciwgRXZlbnRFbWl0dGVyLCBmb3J3YXJkUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IE5HX1ZBTFVFX0FDQ0VTU09SLCBOR19WQUxJREFUT1JTLCBDb250cm9sVmFsdWVBY2Nlc3NvciwgVmFsaWRhdG9yLCBBYnN0cmFjdENvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2h4YS1kYXRlcGlja2VyLWlucHV0LCBoeGEtZGF0ZXBpY2tlci1mb3JtJyxcclxuICB0ZW1wbGF0ZTogYDxkaXYgY2xhc3M9XCJoeC1pbnB1dC1ncm91cCBoeGEtZGF0ZXBpY2tlci1mb3JtXCI+XHJcbiAgPGRpdiBjbGFzcz1cImh4LWlucHV0LWNvbnRyb2xcIiBbbmdDbGFzc109XCJ7J2lzLWRhbmdlcic6ICFpc1ZhbGlkICYmIGRhdGVQaWNrZXJGb3JtLnRvdWNoZWR9XCI+XHJcbiAgICA8aW5wdXQgY2xhc3M9XCJoeC1pbnB1dFwiIHR5cGU9XCJ0ZXh0XCIgI2RhdGVQaWNrZXJGb3JtPVwibmdNb2RlbFwiXHJcbiAgICAgIFtyZXF1aXJlZF09XCJyZXF1aXJlZCA/IHRydWUgOiBudWxsXCJcclxuICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcclxuICAgICAgW3JlYWRvbmx5XT1cInJlYWRvbmx5ID8gdHJ1ZSA6IG51bGxcIlxyXG4gICAgICBbbmdNb2RlbF09XCJkYXRlIHwgZGF0ZTpkYXRlRm9ybWF0XCJcclxuICAgICAgKGNoYW5nZSk9XCJvbkNoYW5nZShkYXRlUGlja2VyRm9ybS52YWx1ZSlcIlxyXG4gICAgICAoZm9jdXMpPVwib25Gb2N1cygpXCJcclxuICAgICAgKGtleWRvd24uVGFiKT1cIm9uVGFiKGRhdGVQaWNrZXJGb3JtLnZhbHVlKVwiPlxyXG4gICAgPGxhYmVsIGNsYXNzPVwiaHgtbGFiZWxcIiAqbmdJZj1cInBsYWNlaG9sZGVyXCI+e3twbGFjZWhvbGRlcn19IDxzdXAgKm5nSWY9XCJyZXF1aXJlZFwiPio8L3N1cD48L2xhYmVsPlxyXG4gICAgPGRpdiBjbGFzcz1cImh4LWhlbHBcIj48L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJoeGEtZGF0ZXBpY2tlci1oZWxwXCI+UGxlYXNlIHNlbGVjdCBhIGRhdGU8L2Rpdj5cclxuICA8L2Rpdj5cclxuICA8aSBjbGFzcz1cImh4LWljb24gaWNvbi1jYWxlbmRhclwiPjwvaT5cclxuICA8aHhhLWRhdGVwaWNrZXIgY2xhc3M9XCJoeGEtZGF0ZXBpY2tlci1jYWxlbmRhclwiICpuZ0lmPVwidmlzaWJsZVwiIFxyXG4gICAgW3NlbGVjdGVkRGF0ZV09XCJkYXRlXCJcclxuICAgIFt2YWxpZGF0b3JzXT1cImRhdGVWYWxpZGF0b3JzXCJcclxuICAgIChvbkRhdGVTZWxlY3RlZCk9XCJvbkRhdGVTZWxlY3RFdmVudCgkZXZlbnQpXCJcclxuICAgIFtuZ0NsYXNzXT1cInsnaHhhLWRhdGVwaWNrZXItY2FsZW5kYXItdG9wJzogYWxpZ24gPT0gJ3RvcCcsICdoeGEtZGF0ZXBpY2tlci1jYWxlbmRhci1ib3R0b20nOiBhbGlnbiA9PSAnYm90dG9tJ31cIj48L2h4YS1kYXRlcGlja2VyPlxyXG48L2Rpdj5cclxuYCxcclxuICBzdHlsZXM6IFtgLmh4YS1kYXRlcGlja2VyLWZvcm17cG9zaXRpb246cmVsYXRpdmU7bWF4LXdpZHRoOjIxcmVtfS5oeGEtZGF0ZXBpY2tlci1jYWxlbmRhcntwb3NpdGlvbjphYnNvbHV0ZTt6LWluZGV4Ojk5O2xlZnQ6MH0uaHhhLWRhdGVwaWNrZXItY2FsZW5kYXItdG9we2JvdHRvbToxMDAlfS5oeGEtZGF0ZXBpY2tlci1jYWxlbmRhci1ib3R0b217dG9wOjcwJX0uaHhhLWRhdGVwaWNrZXItaGVscHtmb250LXNpemU6Ljc1cmVtO21hcmdpbi10b3A6LjI1cmVtO2NvbG9yOiM2MzYwNWZ9Lmh4YS1kYXRlcGlja2VyLWZvcm0gaW5wdXRbcmVhZG9ubHldfi5oeC1sYWJlbHt0b3A6LS41cmVtO2ZvbnQtc2l6ZTouNzVyZW07Y29sb3I6IzQxYjk4N31gXSxcclxuICBwcm92aWRlcnM6IFt7XHJcbiAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVwaWNrZXJGb3JtQ29tcG9uZW50KSxcclxuICAgIG11bHRpOiB0cnVlXHJcbiAgfSxcclxuICB7XHJcbiAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxyXG4gICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRGF0ZXBpY2tlckZvcm1Db21wb25lbnQpLFxyXG4gICAgbXVsdGk6IHRydWUsXHJcbiAgfV1cclxufSlcclxuZXhwb3J0IGNsYXNzIERhdGVwaWNrZXJGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciwgVmFsaWRhdG9yIHtcclxuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHJlYWRvbmx5ID0gZmFsc2U7XHJcbiAgQElucHV0KCkgcmVxdWlyZWQgPSBmYWxzZTtcclxuICBASW5wdXQoKSBkZWZhdWx0VG9QcmVzZW50RGF0ZSA9IHRydWU7XHJcbiAgQElucHV0KCkgYWxsb3dQcmV2aW91c0RhdGVzID0gdHJ1ZTtcclxuICBASW5wdXQoKSBhbGxvd0Z1dHVyZURhdGVzID0gdHJ1ZTtcclxuICBASW5wdXQoKSBkYXRlRm9ybWF0ID0gXCJkZC9NTS95XCI7XHJcbiAgQElucHV0KCkgcGxhY2Vob2xkZXIgPSBcIkRhdGVcIjtcclxuICBASW5wdXQoKSBhbGlnbjogXCJ0b3BcIiB8IFwiYm90dG9tXCIgPSBcImJvdHRvbVwiO1xyXG4gIEBJbnB1dCgpIGZyb20gPSAnJztcclxuICBASW5wdXQoKSB0byA9ICcnO1xyXG5cclxuICBAT3V0cHV0KCkgb25EYXRlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8RGF0ZT4gPSBuZXcgRXZlbnRFbWl0dGVyPERhdGU+KCk7XHJcblxyXG4gIHB1YmxpYyBkYXRlOiBEYXRlO1xyXG4gIHB1YmxpYyB2aXNpYmxlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgcHVibGljIHByZXNlbnREYXRlOiBEYXRlO1xyXG4gIHB1YmxpYyBpc1ZhbGlkOiBib29sZWFuO1xyXG4gIHB1YmxpYyBkYXRlVmFsaWRhdG9ycyA9IG5ldyBBcnJheTwoZGF0ZTogRGF0ZSkgPT4gYm9vbGVhbj4oKTtcclxuICBwcml2YXRlIG9uQ2hhbmdlZCA9IG5ldyBBcnJheTwodmFsdWU6IERhdGUpID0+IHZvaWQ+KCk7XHJcbiAgcHJpdmF0ZSBvblRvdWNoZWQgPSBuZXcgQXJyYXk8KCkgPT4gdm9pZD4oKTtcclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZURhdGVSYW5nZTogKGRhdGU6IERhdGUpID0+IGJvb2xlYW47XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudDogRWxlbWVudFJlZikgeyB9XHJcblxyXG4gIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgY29uc3QgZGF0ZTogRGF0ZSA9IG5ldyBEYXRlKCk7XHJcbiAgICB0aGlzLnByZXNlbnREYXRlID0gbmV3IERhdGUoZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RGF0ZSgpKTtcclxuXHJcbiAgICBpZiAodGhpcy5kZWZhdWx0VG9QcmVzZW50RGF0ZSkge1xyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICB0aGlzLnNldERhdGUodGhpcy5wcmVzZW50RGF0ZSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSAgICBcclxuXHJcbiAgICAvLyBDbG9zZSB0byB0aGUgbWluaW11bSBhbmQgbWF4aXVtIHBvc3NpYmxlIGRhdGVzLCBidXQgc3RpbGwgbm9ybWFsaXNhYmxlXHJcbiAgICAvLyBodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi81LjEvI3NlYy0xNS45LjEuMVxyXG4gICAgY29uc3QgZnJvbSA9IHRoaXMucGFyc2VEYXRlKHRoaXMuZnJvbSkgfHwgbmV3IERhdGUoLTg2MzAwMDAwMDAwMDAwMDApO1xyXG4gICAgY29uc3QgdG8gPSB0aGlzLnBhcnNlRGF0ZSh0aGlzLnRvKSB8fCBuZXcgRGF0ZSg4NjMwMDAwMDAwMDAwMDAwKTtcclxuXHJcbiAgICBpZiAoISF0aGlzLmZyb20gfHwgISF0aGlzLnRvKSB7XHJcbiAgICAgIHRoaXMudmFsaWRhdGVEYXRlUmFuZ2UgPSB0aGlzLmNyZWF0ZURhdGVSYW5nZVZhbGlkYXRvcihmcm9tLCB0byk7XHJcbiAgICAgIHRoaXMuZGF0ZVZhbGlkYXRvcnMucHVzaCh0aGlzLnZhbGlkYXRlRGF0ZVJhbmdlLmJpbmQodGhpcykpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghdGhpcy5hbGxvd1ByZXZpb3VzRGF0ZXMpXHJcbiAgICAgIHRoaXMuZGF0ZVZhbGlkYXRvcnMucHVzaCh0aGlzLnZhbGlkYXRlSXNOb3RCZWZvcmVEYXRlLmJpbmQodGhpcykpO1xyXG4gICAgaWYgKCF0aGlzLmFsbG93RnV0dXJlRGF0ZXMpXHJcbiAgICAgIHRoaXMuZGF0ZVZhbGlkYXRvcnMucHVzaCh0aGlzLnZhbGlkYXRlSXNOb3RBZnRlckRhdGUuYmluZCh0aGlzKSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc2V0RGF0ZShkYXRlOiBEYXRlKTogdm9pZCB7XHJcbiAgICB0aGlzLmRhdGUgPSBkYXRlO1xyXG4gICAgdGhpcy5vbkRhdGVDaGFuZ2UuZW1pdChkYXRlKTtcclxuICAgIHRoaXMucHJvcG9nYXRlQ2hhbmdlKGRhdGUpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHNldFZpc2libGUoKTogdm9pZCB7XHJcbiAgICB0aGlzLnZpc2libGUgPSB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHVuc2V0VmlzaWJsZSgpOiB2b2lkIHtcclxuICAgIHRoaXMudmlzaWJsZSA9IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudC50YXJnZXQnXSlcclxuICBwdWJsaWMgb25DbGlja091dHNpZGVDb21wb25lbnQodGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZmlyc3RDaGlsZC5jb250YWlucyh0YXJnZXRFbGVtZW50KSkge1xyXG4gICAgICB0aGlzLnVuc2V0VmlzaWJsZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIG9uRGF0ZVNlbGVjdEV2ZW50KGlucHV0RGF0ZTogRGF0ZSk6IHZvaWQge1xyXG4gICAgdGhpcy51bnNldFZpc2libGUoKTtcclxuICAgIHRoaXMuc2V0RGF0ZShpbnB1dERhdGUpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG9uQ2hhbmdlKGlucHV0RGF0ZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBkYXRlOiBEYXRlID0gdGhpcy5wYXJzZURhdGUoaW5wdXREYXRlKTtcclxuXHJcbiAgICBpZiAoaW5wdXREYXRlID09IFwiXCIpIHtcclxuICAgICAgdGhpcy5zZXREYXRlKG51bGwpO1xyXG4gICAgfSBlbHNlIGlmICghIWRhdGUpIHtcclxuICAgICAgdGhpcy5zZXREYXRlKGRhdGUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5wcm9wb2dhdGVDaGFuZ2UoaW5wdXREYXRlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBvbkZvY3VzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zZXRWaXNpYmxlKCk7XHJcbiAgICB0aGlzLnByb3BvZ2F0ZVRvdWNoZWQoKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvblRhYihpbnB1dERhdGU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5vbkNoYW5nZShpbnB1dERhdGUpO1xyXG4gICAgdGhpcy51bnNldFZpc2libGUoKTtcclxuICAgIHRoaXMucHJvcG9nYXRlVG91Y2hlZCgpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHBhcnNlRGF0ZShpbnB1dERhdGU6IHN0cmluZyk6IERhdGUge1xyXG4gICAgLy8gU2luY2UgRGF0ZS5QYXJzZSgpIG9ubHkgYWNjZXBzIG0vZC95IGRhdGVzLCB3ZSBoYXZlIHRvIHN3YXAgdGhlIGRheSBhbmQgbW9udGhcclxuICAgIGxldCBkYXRlQXJyYXkgPSBpbnB1dERhdGUuc3BsaXQoL1suLFxcLyAtXS8pO1xyXG4gICAgaWYgKGRhdGVBcnJheS5sZW5ndGggPT0gMyAmJiBkYXRlQXJyYXlbMl0ubGVuZ3RoICE9IDApIHtcclxuICAgICAgbGV0IGRheTogc3RyaW5nID0gZGF0ZUFycmF5LnNoaWZ0KCk7XHJcbiAgICAgIGRhdGVBcnJheS5zcGxpY2UoMSwgMCwgZGF5KTtcclxuXHJcbiAgICAgIGxldCBwYXJzZUlucHV0OiBudW1iZXIgPSBEYXRlLnBhcnNlKGRhdGVBcnJheS5qb2luKFwiL1wiKSk7XHJcbiAgICAgIGlmICghaXNOYU4ocGFyc2VJbnB1dCkpIHtcclxuICAgICAgICByZXR1cm4gbmV3IERhdGUocGFyc2VJbnB1dCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHZhbGlkYXRlSXNOb3RCZWZvcmVEYXRlKGRhdGU6IERhdGUpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IG5vcm1hbGlzZWREYXRlID0gbmV3IERhdGUoZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RGF0ZSgpKTtcclxuXHJcbiAgICByZXR1cm4gbm9ybWFsaXNlZERhdGUuZ2V0VGltZSgpIDwgdGhpcy5wcmVzZW50RGF0ZS5nZXRUaW1lKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgdmFsaWRhdGVJc05vdEFmdGVyRGF0ZShkYXRlOiBEYXRlKTogYm9vbGVhbiB7XHJcbiAgICBjb25zdCBub3JtYWxpc2VkRGF0ZSA9IG5ldyBEYXRlKGRhdGUuZ2V0RnVsbFllYXIoKSwgZGF0ZS5nZXRNb250aCgpLCBkYXRlLmdldERhdGUoKSk7XHJcblxyXG4gICAgcmV0dXJuIG5vcm1hbGlzZWREYXRlLmdldFRpbWUoKSA+IHRoaXMucHJlc2VudERhdGUuZ2V0VGltZSgpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGNyZWF0ZURhdGVSYW5nZVZhbGlkYXRvcihmcm9tOiBEYXRlLCB0bzogRGF0ZSk6IChkYXRlOiBEYXRlKSA9PiBib29sZWFuIHtcclxuICAgIGNvbnN0IG5vcm1hbGlzZWRGcm9tRGF0ZSA9IG5ldyBEYXRlKGZyb20uZ2V0RnVsbFllYXIoKSwgZnJvbS5nZXRNb250aCgpLCBmcm9tLmdldERhdGUoKSk7XHJcbiAgICBjb25zdCBub3JtYWxpc2VkVG9EYXRlID0gbmV3IERhdGUodG8uZ2V0RnVsbFllYXIoKSwgdG8uZ2V0TW9udGgoKSwgdG8uZ2V0RGF0ZSgpKTtcclxuXHJcbiAgICByZXR1cm4gKGRhdGU6IERhdGUpID0+IHtcclxuICAgICAgY29uc3Qgbm9ybWFsaXNlZERhdGUgPSBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSwgZGF0ZS5nZXREYXRlKCkpO1xyXG4gICAgICByZXR1cm4gIShub3JtYWxpc2VkRnJvbURhdGUuZ2V0VGltZSgpIDw9IG5vcm1hbGlzZWREYXRlLmdldFRpbWUoKSAmJlxyXG4gICAgICAgIG5vcm1hbGlzZWREYXRlLmdldFRpbWUoKSA8PSBub3JtYWxpc2VkVG9EYXRlLmdldFRpbWUoKSk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHdyaXRlVmFsdWUodmFsdWU6IERhdGUpOiB2b2lkIHtcclxuICAgIHRoaXMuc2V0RGF0ZSh2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHZhbHVlOiBEYXRlKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICB0aGlzLm9uQ2hhbmdlZC5wdXNoKGZuKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyByZWdpc3Rlck9uVG91Y2hlZChmbjogKCkgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgdGhpcy5vblRvdWNoZWQucHVzaChmbik7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgcHJvcG9nYXRlVG91Y2hlZCgpOiB2b2lkIHtcclxuICAgIHRoaXMub25Ub3VjaGVkLmZvckVhY2goZm4gPT4gZm4oKSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgcHJvcG9nYXRlQ2hhbmdlKHZhbHVlKTogdm9pZCB7XHJcbiAgICB0aGlzLm9uQ2hhbmdlZC5mb3JFYWNoKGZuID0+IGZuKHZhbHVlKSk7XHJcbiAgfVxyXG5cclxuICB2YWxpZGF0ZShjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiB7IFtrZXk6IHN0cmluZ106IGFueTsgfSB7XHJcbiAgICBjb25zdCBkYXRlID0gRGF0ZS5wYXJzZShjb250cm9sLnZhbHVlKTtcclxuXHJcbiAgICBpZiAoIXRoaXMucmVxdWlyZWQgJiYgKGNvbnRyb2wudmFsdWUgPT09IG51bGwgfHwgY29udHJvbC52YWx1ZSA9PT0gdW5kZWZpbmVkKSkge1xyXG4gICAgICB0aGlzLmlzVmFsaWQgPSB0cnVlO1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoaXNOYU4oZGF0ZSkpIHtcclxuICAgICAgdGhpcy5pc1ZhbGlkID0gZmFsc2U7XHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgZGF0ZVBhcnNlRXJyb3I6IHtcclxuICAgICAgICAgIHZhbGlkOiBmYWxzZVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICghdGhpcy5hbGxvd1ByZXZpb3VzRGF0ZXMgJiYgdGhpcy52YWxpZGF0ZUlzTm90QmVmb3JlRGF0ZSh0aGlzLmRhdGUpKSB7XHJcbiAgICAgIHRoaXMuaXNWYWxpZCA9IGZhbHNlO1xyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIHByZXZpb3VzRGF0ZUVycm9yOiB7XHJcbiAgICAgICAgICB2YWxpZDogZmFsc2VcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXRoaXMuYWxsb3dGdXR1cmVEYXRlcyAmJiB0aGlzLnZhbGlkYXRlSXNOb3RBZnRlckRhdGUodGhpcy5kYXRlKSkge1xyXG4gICAgICB0aGlzLmlzVmFsaWQgPSBmYWxzZTtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBmdXR1cmVEYXRlRXJyb3I6IHtcclxuICAgICAgICAgIHZhbGlkOiBmYWxzZVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnZhbGlkYXRlRGF0ZVJhbmdlICYmIHRoaXMudmFsaWRhdGVEYXRlUmFuZ2UodGhpcy5kYXRlKSkge1xyXG4gICAgICB0aGlzLmlzVmFsaWQgPSBmYWxzZTtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBkYXRlUmFuZ2VFcnJvcjoge1xyXG4gICAgICAgICAgdmFsaWQ6IGZhbHNlXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMucmVxdWlyZWQgJiYgIXRoaXMuZGF0ZSkge1xyXG4gICAgICB0aGlzLmlzVmFsaWQgPSBmYWxzZTtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBkYXRlUmVxdWlyZWRFcnJvcjoge1xyXG4gICAgICAgICAgdmFsaWQ6IGZhbHNlXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5pc1ZhbGlkID0gdHJ1ZTtcclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxufVxyXG4iXX0=