UNPKG

@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
/** * @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=