UNPKG

@hxui/angular

Version:

* * *

643 lines 63.9 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ import { Component, Input, Output, ElementRef, EventEmitter, forwardRef, NgZone, ComponentFactoryResolver, ViewContainerRef, Optional } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; import { Overlay, ScrollDispatcher } from '@angular/cdk/overlay'; import { ComponentPortal } from '@angular/cdk/portal'; import { Subject } from 'rxjs/index'; import { DatepickerComponent } from './datepicker.component'; import { take, takeUntil } from 'rxjs/operators'; import { Directionality } from '@angular/cdk/bidi'; import { DatepickerConfig } from './datepicker.config'; export class DatepickerFormComponent { /** * @param {?} _elementRef * @param {?} _viewContainerRef * @param {?} overlay * @param {?} _ngZone * @param {?} _scrollDispatcher * @param {?} _componentFactoryResolver * @param {?} _config * @param {?} _dir */ constructor(_elementRef, _viewContainerRef, overlay, _ngZone, _scrollDispatcher, _componentFactoryResolver, _config, _dir) { this._elementRef = _elementRef; this._viewContainerRef = _viewContainerRef; this.overlay = overlay; this._ngZone = _ngZone; this._scrollDispatcher = _scrollDispatcher; this._componentFactoryResolver = _componentFactoryResolver; this._config = _config; this._dir = _dir; this._destroyed = new Subject(); 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.helpText = 'Please select a date'; this.icon = 'hx-icon icon-calendar'; this.iconPlacement = 'right'; this.placement = 'bottom'; this.showDelay = this._config.showDelay; this.hideDelay = this._config.hideDelay; this.from = ''; this.to = ''; this.interval = false; this.dueDateInterval = '0 day(s)'; // '1 week(s)' | '2 month(s)' | '3 year(s)' // '1 week(s)' | '2 month(s)' | '3 year(s)' this.onDateChange = new EventEmitter(); this.visible = false; this.dateValidators = new Array(); this.onChanged = new Array(); this.onTouched = new Array(); this.onDateSelectEvent = (inputDate) => { this._hide(); this.setDate(inputDate); }; // get input reference this._elementHtmlCollection = this._elementRef.nativeElement.getElementsByTagName('input'); } /** * Dispose the tooltip when destroyed. * @return {?} */ ngOnDestroy() { if (this._overlayRef) { this._overlayRef.dispose(); this._calendarInstance = null; } this._destroyed.next(); this._destroyed.complete(); } /** * @return {?} */ ngOnInit() { // set element ref which will be used for dropdown positioning this._elementHtmlRef = this._elementHtmlCollection.item(0); /** @type {?} */ const 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 /** @type {?} */ const from = this.parseDate(this.from) || new Date(-8630000000000000); /** @type {?} */ const 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); } /** * @param {?} inputDate * @return {?} */ onChange(inputDate) { /** @type {?} */ const date = this.parseDate(inputDate); if (inputDate === '') { this.setDate(null); } else if (!!date) { this.setDate(date); } else { this.propogateChange(inputDate); } } /** * @return {?} */ onFocus() { this._show(); this.propogateTouched(); } /** * @param {?} inputDate * @return {?} */ onTab(inputDate) { this.onChange(inputDate); this._hide(); this.propogateTouched(); } /** * @param {?} inputDate * @return {?} */ parseDate(inputDate) { // Since Date.Parse() only acceps m/d/y dates, we have to swap the day and month /** @type {?} */ const dateArray = inputDate.split(/[.,\/ -]/); if (dateArray.length === 3 && dateArray[2].length !== 0) { /** @type {?} */ const day = dateArray.shift(); dateArray.splice(1, 0, day); /** @type {?} */ const parseInput = Date.parse(dateArray.join('/')); if (!isNaN(parseInput)) { return new Date(parseInput); } } return null; } /** * @param {?} date * @return {?} */ validateIsNotBeforeDate(date) { /** @type {?} */ const normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); return normalisedDate.getTime() <= this.presentDate.getTime(); } /** * @param {?} date * @return {?} */ validateIsNotAfterDate(date) { /** @type {?} */ const normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); return normalisedDate.getTime() >= this.presentDate.getTime(); } /** * @param {?} from * @param {?} to * @return {?} */ createDateRangeValidator(from, to) { /** @type {?} */ const normalisedFromDate = new Date(from.getFullYear(), from.getMonth(), from.getDate()); /** @type {?} */ const normalisedToDate = new Date(to.getFullYear(), to.getMonth(), to.getDate()); return (date) => { /** @type {?} */ const normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); return !(normalisedFromDate.getTime() <= normalisedDate.getTime() && normalisedDate.getTime() <= normalisedToDate.getTime()); }; } /** * @param {?} value * @return {?} */ writeValue(value) { if (value !== this.date) { 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) { /** @type {?} */ const 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; } /** * @param {?=} delay * @return {?} */ _show(delay = this.showDelay) { if (this.disabled) { return; } /** @type {?} */ const overlayRef = this._createOverlay(); this._detach(); this._portal = this._portal || new ComponentPortal(DatepickerComponent, this._viewContainerRef); this._calendarInstance = overlayRef.attach(this._portal).instance; this._calendarInstance.afterHidden() .pipe(takeUntil(this._destroyed)) .subscribe(() => this._detach()); this._updateTooltipContent(); (/** @type {?} */ (this._calendarInstance)).show(delay); } /** * @param {?=} delay * @return {?} */ _hide(delay = this.hideDelay) { if (this._calendarInstance) { this._calendarInstance.hide(delay); } } /** * @return {?} */ _createOverlay() { if (this._overlayRef) { return this._overlayRef; } /** @type {?} */ const positionStrategy = this.overlay.position() .flexibleConnectedTo((/** @type {?} */ (this._elementHtmlRef))) .withTransformOriginOn('.hxa-datepicker-control') .withFlexibleDimensions(false); this._overlayRef = this.overlay.create({ positionStrategy: positionStrategy, panelClass: 'hxa-datepicker-calendar', hasBackdrop: true, backdropClass: 'cdk-overlay-transparent-backdrop', scrollStrategy: this.overlay.scrollStrategies.reposition() }); this._updatePosition(); this._overlayRef.detachments() .pipe(takeUntil(this._destroyed)) .subscribe(() => this._detach()); this._overlayRef.backdropClick(). subscribe(() => this._hide()); /** @type {?} */ const position = (/** @type {?} */ (this._overlayRef.getConfig().positionStrategy)); position.positionChanges .pipe(takeUntil(this._destroyed)) .subscribe((pos) => { if (pos.connectionPair.originX === 'start') { this.placement = 'left'; } else if (pos.connectionPair.originX === 'end') { this.placement = 'right'; } this._updateTooltipContent(); }); return this._overlayRef; } /** * @return {?} */ _updatePosition() { /** @type {?} */ const position = (/** @type {?} */ ((/** @type {?} */ (this._overlayRef)).getConfig().positionStrategy)); /** @type {?} */ const origin = this._getOrigin(); /** @type {?} */ const overlay = this._getOverlayPosition(); position.withPositions([ Object.assign({}, origin.main, overlay.main), Object.assign({}, origin.fallback, overlay.fallback) ]); } /** * Returns the origin position and a fallback position based on the user's position preference. * The fallback position is the inverse of the origin (e.g. `'bottom' -> 'top'`). * @return {?} */ _getOrigin() { /** @type {?} */ const placement = this.placement; /** @type {?} */ let originPlacement; if (placement === 'top' || placement === 'bottom') { originPlacement = { originX: 'start', originY: placement === 'top' ? 'top' : 'bottom' }; } else if (placement === 'left') { originPlacement = { originX: 'start', originY: 'center' }; } else if (placement === 'right') { originPlacement = { originX: 'end', originY: 'center' }; } else { console.error('Position error', placement); } const { x, y } = this._invertPosition(originPlacement.originX, originPlacement.originY); return { main: originPlacement, fallback: { originX: x, originY: y } }; } /** * Returns the overlay position and a fallback position based on the user's preference * @return {?} */ _getOverlayPosition() { /** @type {?} */ const placement = this.placement; /** @type {?} */ let overlayPlacement; if (placement === 'top') { overlayPlacement = { overlayX: 'start', overlayY: 'bottom' }; } else if (placement === 'bottom') { overlayPlacement = { overlayX: 'start', overlayY: 'top' }; } else if (placement === 'left') { overlayPlacement = { overlayX: 'end', overlayY: 'center' }; } else if (placement === 'right') { overlayPlacement = { overlayX: 'start', overlayY: 'center' }; } else { console.error('Could not find a position', placement); } const { x, y } = this._invertPosition(overlayPlacement.overlayX, overlayPlacement.overlayY); return { main: overlayPlacement, fallback: { overlayX: x, overlayY: y } }; } /** * @param {?} x * @param {?} y * @return {?} */ _invertPosition(x, y) { if (this.placement === 'top' || this.placement === 'bottom') { if (y === 'top') { y = 'bottom'; } else if (y === 'bottom') { y = 'top'; } } else { if (x === 'end') { x = 'start'; } else if (x === 'start') { x = 'end'; } } return { x, y }; } /** * @return {?} */ _detach() { if (this._overlayRef && this._overlayRef.hasAttached()) { this._overlayRef.detach(); } this._calendarInstance = null; } /** * Updates the tooltip content and repositions the overlay according to the new content length * @return {?} */ _updateTooltipContent() { // Must wait for the content to be painted to the tooltip so that the overlay can properly // calculate the correct positioning based on the size of its contents. if (this._calendarInstance) { this._calendarInstance.selectedDate = this.date; this._calendarInstance.placement = this.placement; this._calendarInstance.validators = this.dateValidators; this._calendarInstance.onDateSelected = this.onDateSelectEvent; this._calendarInstance.allowInterval = this.interval; this._calendarInstance.selectedDueDateInterval = this.dueDateInterval; this._ngZone.onMicrotaskEmpty.asObservable().pipe(take(1), takeUntil(this._destroyed)).subscribe(() => { if (this._calendarInstance) { (/** @type {?} */ (this._overlayRef)).updatePosition(); } }); } } } DatepickerFormComponent.decorators = [ { type: Component, args: [{ selector: 'hxa-datepicker-input, hxa-datepicker-form', template: `<div class="hx-input-group hxa-datepicker-form"> <i class="{{icon}}" *ngIf="iconPlacement === 'left'"></i> <div class="hx-input-control hxa-datepicker-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">{{helpText}}</div> </div> <i class="{{icon}}" *ngIf="iconPlacement === 'right'"></i> </div> `, styles: [`.hxa-datepicker-form{position:relative;max-width:19rem}.hxa-datepicker-control{margin:0}.hxa-datepicker-calendar{position:absolute;z-index:99;left:0;max-width:19rem}.hxa-datepicker-calendar-top{bottom:100%}.hxa-datepicker-calendar-bottom{top:70%}.hxa-datepicker-calendar hxa-datepicker{max-width:19rem}.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}hxa-datepicker{border:1px solid #d3d3d3;max-width:19rem}`], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DatepickerFormComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => DatepickerFormComponent), multi: true, }] },] }, ]; /** @nocollapse */ DatepickerFormComponent.ctorParameters = () => [ { type: ElementRef }, { type: ViewContainerRef }, { type: Overlay }, { type: NgZone }, { type: ScrollDispatcher }, { type: ComponentFactoryResolver }, { type: DatepickerConfig }, { type: Directionality, decorators: [{ type: Optional }] } ]; 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 }], helpText: [{ type: Input }], icon: [{ type: Input }], iconPlacement: [{ type: Input }], placement: [{ type: Input }], showDelay: [{ type: Input }], hideDelay: [{ type: Input }], from: [{ type: Input }], to: [{ type: Input }], interval: [{ type: Input }], dueDateInterval: [{ type: Input }], onDateChange: [{ type: Output }] }; if (false) { /** @type {?} */ DatepickerFormComponent.prototype._overlayRef; /** @type {?} */ DatepickerFormComponent.prototype._calendarInstance; /** @type {?} */ DatepickerFormComponent.prototype._portal; /** @type {?} */ DatepickerFormComponent.prototype._destroyed; /** @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.helpText; /** @type {?} */ DatepickerFormComponent.prototype.icon; /** @type {?} */ DatepickerFormComponent.prototype.iconPlacement; /** @type {?} */ DatepickerFormComponent.prototype.placement; /** @type {?} */ DatepickerFormComponent.prototype.showDelay; /** @type {?} */ DatepickerFormComponent.prototype.hideDelay; /** @type {?} */ DatepickerFormComponent.prototype.from; /** @type {?} */ DatepickerFormComponent.prototype.to; /** @type {?} */ DatepickerFormComponent.prototype.interval; /** @type {?} */ DatepickerFormComponent.prototype.dueDateInterval; /** @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._elementHtmlRef; /** @type {?} */ DatepickerFormComponent.prototype._elementHtmlCollection; /** @type {?} */ DatepickerFormComponent.prototype.onDateSelectEvent; /** @type {?} */ DatepickerFormComponent.prototype._elementRef; /** @type {?} */ DatepickerFormComponent.prototype._viewContainerRef; /** @type {?} */ DatepickerFormComponent.prototype.overlay; /** @type {?} */ DatepickerFormComponent.prototype._ngZone; /** @type {?} */ DatepickerFormComponent.prototype._scrollDispatcher; /** @type {?} */ DatepickerFormComponent.prototype._componentFactoryResolver; /** @type {?} */ DatepickerFormComponent.prototype._config; /** @type {?} */ DatepickerFormComponent.prototype._dir; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BoeHVpL2FuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZGF0ZXBpY2tlci9kYXRlcGlja2VyLWZvcm0uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQVUsVUFBVSxFQUFnQixZQUFZLEVBQUUsVUFBVSxFQUN6RSxNQUFNLEVBQUUsd0JBQXdCLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxFQUN4RSxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsYUFBYSxFQUFvRCxNQUFNLGdCQUFnQixDQUFDO0FBQ3BILE9BQU8sRUFHcUIsT0FBTyxFQUNqQyxnQkFBZ0IsRUFDakIsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLFlBQVksQ0FBQztBQUNuQyxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUMzRCxPQUFPLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQy9DLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUNqRCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQWlDckQsTUFBTSxPQUFPLHVCQUF1Qjs7Ozs7Ozs7Ozs7SUE0RWxDLFlBQW9CLFdBQXVCLEVBQ3ZCLGlCQUFtQyxFQUNwQyxPQUFnQixFQUNmLE9BQWUsRUFDZixpQkFBbUMsRUFDbkMseUJBQW1ELEVBQ25ELE9BQXlCLEVBQ2IsSUFBb0I7UUFQaEMsZ0JBQVcsR0FBWCxXQUFXLENBQVk7UUFDdkIsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFrQjtRQUNwQyxZQUFPLEdB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QWdCO1lBRGhCLGNBQWMsdUJBcUhQLFFBQVE7Ozt1QkE1RXBCLEtBQUs7dUJBR0wsS0FBSzt1QkFHTCxLQUFLO21DQUdMLEtBQUs7aUNBR0wsS0FBSzsrQkFHTCxLQUFLO3lCQUdMLEtBQUs7MEJBR0wsS0FBSzt1QkFHTCxLQUFLO21CQUdMLEtBQUs7NEJBR0wsS0FBSzt3QkFHTCxLQUFLO3dCQUdMLEtBQUs7d0JBR0wsS0FBSzttQkFHTCxLQUFLO2lCQUdMLEtBQUs7dUJBR0wsS0FBSzs4QkFHTCxLQUFLOzJCQUdMLE1BQU07Ozs7SUEzRFAsOENBQStCOztJQUMvQixvREFBOEM7O0lBQzlDLDBDQUFzRDs7SUFDdEQsNkNBQTRDOztJQUU1QywyQ0FDaUI7O0lBRWpCLDJDQUNpQjs7SUFFakIsMkNBQ2lCOztJQUVqQix1REFDNEI7O0lBRTVCLHFEQUMwQjs7SUFFMUIsbURBQ3dCOztJQUV4Qiw2Q0FDdUI7O0lBRXZCLDhDQUNxQjs7SUFFckIsMkNBQ2tDOztJQUVsQyx1Q0FDK0I7O0lBRS9CLGdEQUN3Qjs7SUFFeEIsNENBQzBEOztJQUUxRCw0Q0FDbUM7O0lBRW5DLDRDQUNtQzs7SUFFbkMsdUNBQ1U7O0lBRVYscUNBQ1E7O0lBRVIsMkNBQ2lCOztJQUVqQixrREFDNkI7O0lBRTdCLCtDQUM0RDs7SUFFNUQsdUNBQWtCOztJQUNsQiwwQ0FBdUI7O0lBQ3ZCLDhDQUF5Qjs7SUFDekIsMENBQXdCOztJQUN4QixpREFBNkQ7O0lBQzdELDRDQUF1RDs7SUFDdkQsNENBQTRDOztJQUU1QyxvREFBbUQ7O0lBQ25ELGtEQUFpQzs7SUFDakMseURBQStDOztJQWtFL0Msb0RBR0M7O0lBbkVXLDhDQUErQjs7SUFDL0Isb0RBQTJDOztJQUMzQywwQ0FBdUI7O0lBQ3ZCLDBDQUF1Qjs7SUFDdkIsb0RBQTJDOztJQUMzQyw0REFBMkQ7O0lBQzNELDBDQUFpQzs7SUFDakMsdUNBQXdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIE9uSW5pdCwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsXHJcbiAgT25EZXN0cm95LCBOZ1pvbmUsIENvbXBvbmVudEZhY3RvcnlSZXNvbHZlciwgVmlld0NvbnRhaW5lclJlZiwgT3B0aW9uYWwsIFZpZXdDaGlsZCwgQ29udGVudENoaWxkXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IE5HX1ZBTFVFX0FDQ0VTU09SLCBOR19WQUxJREFUT1JTLCBDb250cm9sVmFsdWVBY2Nlc3NvciwgVmFsaWRhdG9yLCBBYnN0cmFjdENvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7XHJcbiAgRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5LFxyXG4gIEhvcml6b250YWxDb25uZWN0aW9uUG9zLFxyXG4gIE9yaWdpbkNvbm5lY3Rpb25Qb3NpdGlvbiwgT3ZlcmxheSwgT3ZlcmxheUNvbm5lY3Rpb25Qb3NpdGlvbiwgT3ZlcmxheVJlZixcclxuICBTY3JvbGxEaXNwYXRjaGVyLCBWZXJ0aWNhbENvbm5lY3Rpb25Qb3NcclxufSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XHJcbmltcG9ydCB7Q29tcG9uZW50UG9ydGFsfSBmcm9tICdAYW5ndWxhci9jZGsvcG9ydGFsJztcclxuaW1wb3J0IHtTdWJqZWN0fSBmcm9tICdyeGpzL2luZGV4JztcclxuaW1wb3J0IHtEYXRlcGlja2VyQ29tcG9uZW50fSBmcm9tICcuL2RhdGVwaWNrZXIuY29tcG9uZW50JztcclxuaW1wb3J0IHt0YWtlLCB0YWtlVW50aWx9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHtEaXJlY3Rpb25hbGl0eX0gZnJvbSAnQGFuZ3VsYXIvY2RrL2JpZGknO1xyXG5pbXBvcnQge0RhdGVwaWNrZXJDb25maWd9IGZyb20gJy4vZGF0ZXBpY2tlci5jb25maWcnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdoeGEtZGF0ZXBpY2tlci1pbnB1dCwgaHhhLWRhdGVwaWNrZXItZm9ybScsXHJcbiAgdGVtcGxhdGU6IGA8ZGl2IGNsYXNzPVwiaHgtaW5wdXQtZ3JvdXAgaHhhLWRhdGVwaWNrZXItZm9ybVwiPlxyXG4gIDxpIGNsYXNzPVwie3tpY29ufX1cIiAqbmdJZj1cImljb25QbGFjZW1lbnQgPT09ICdsZWZ0J1wiPjwvaT5cclxuICA8ZGl2IGNsYXNzPVwiaHgtaW5wdXQtY29udHJvbCBoeGEtZGF0ZXBpY2tlci1jb250cm9sXCIgW25nQ2xhc3NdPVwieydpcy1kYW5nZXInOiAhaXNWYWxpZCAmJiBkYXRlUGlja2VyRm9ybS50b3VjaGVkfVwiPlxyXG4gICAgPGlucHV0IGNsYXNzPVwiaHgtaW5wdXRcIiB0eXBlPVwidGV4dFwiICNkYXRlUGlja2VyRm9ybT1cIm5nTW9kZWxcIlxyXG4gICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWQgPyB0cnVlIDogbnVsbFwiXHJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXHJcbiAgICAgIFtyZWFkb25seV09XCJyZWFkb25seSA/IHRydWUgOiBudWxsXCJcclxuICAgICAgW25nTW9kZWxdPVwiZGF0ZSB8IGRhdGU6ZGF0ZUZvcm1hdFwiXHJcbiAgICAgIChjaGFuZ2UpPVwib25DaGFuZ2UoZGF0ZVBpY2tlckZvcm0udmFsdWUpXCJcclxuICAgICAgKGZvY3VzKT1cIm9uRm9jdXMoKVwiXHJcbiAgICAgIChrZXlkb3duLlRhYik9XCJvblRhYihkYXRlUGlja2VyRm9ybS52YWx1ZSlcIj5cclxuICAgIDxsYWJlbCBjbGFzcz1cImh4LWxhYmVsXCIgKm5nSWY9XCJwbGFjZWhvbGRlclwiPnt7cGxhY2Vob2xkZXJ9fSA8c3VwICpuZ0lmPVwicmVxdWlyZWRcIj4qPC9zdXA+PC9sYWJlbD5cclxuICAgIDxkaXYgY2xhc3M9XCJoeC1oZWxwXCI+e3toZWxwVGV4dH19PC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGkgY2xhc3M9XCJ7e2ljb259fVwiICpuZ0lmPVwiaWNvblBsYWNlbWVudCA9PT0gJ3JpZ2h0J1wiPjwvaT5cclxuPC9kaXY+XHJcbmAsXHJcbiAgc3R5bGVzOiBbYC5oeGEtZGF0ZXBpY2tlci1mb3Jte3Bvc2l0aW9uOnJlbGF0aXZlO21heC13aWR0aDoxOXJlbX0uaHhhLWRhdGVwaWNrZXItY29udHJvbHttYXJnaW46MH0uaHhhLWRhdGVwaWNrZXItY2FsZW5kYXJ7cG9zaXRpb246YWJzb2x1dGU7ei1pbmRleDo5OTtsZWZ0OjA7bWF4LXdpZHRoOjE5cmVtfS5oeGEtZGF0ZXBpY2tlci1jYWxlbmRhci10b3B7Ym90dG9tOjEwMCV9Lmh4YS1kYXRlcGlja2VyLWNhbGVuZGFyLWJvdHRvbXt0b3A6NzAlfS5oeGEtZGF0ZXBpY2tlci1jYWxlbmRhciBoeGEtZGF0ZXBpY2tlcnttYXgtd2lkdGg6MTlyZW19Lmh4YS1kYXRlcGlja2VyLWhlbHB7Zm9udC1zaXplOi43NXJlbTttYXJnaW4tdG9wOi4yNXJlbTtjb2xvcjojNjM2MDVmfS5oeGEtZGF0ZXBpY2tlci1mb3JtIGlucHV0W3JlYWRvbmx5XX4uaHgtbGFiZWx7dG9wOi0uNXJlbTtmb250LXNpemU6Ljc1cmVtO2NvbG9yOiM0MWI5ODd9aHhhLWRhdGVwaWNrZXJ7Ym9yZGVyOjFweCBzb2xpZCAjZDNkM2QzO21heC13aWR0aDoxOXJlbX1gXSxcclxuICBwcm92aWRlcnM6IFt7XHJcbiAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVwaWNrZXJGb3JtQ29tcG9uZW50KSxcclxuICAgIG11bHRpOiB0cnVlXHJcbiAgfSxcclxuICB7XHJcbiAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxyXG4gICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRGF0ZXBpY2tlckZvcm1Db21wb25lbnQpLFxyXG4gICAgbXVsdGk6IHRydWUsXHJcbiAgfV1cclxufSlcclxuZXhwb3J0IGNsYXNzIERhdGVwaWNrZXJGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciwgVmFsaWRhdG9yLCBPbkRlc3Ryb3kge1xyXG5cclxuICBfb3ZlcmxheVJlZjogT3ZlcmxheVJlZiB8IG51bGw7XHJcbiAgX2NhbGVuZGFySW5zdGFuY2U6IERhdGVwaWNrZXJDb21wb25lbnQgfCBudWxsO1xyXG4gIHByaXZhdGUgX3BvcnRhbDogQ29tcG9uZW50UG9ydGFsPERhdGVwaWNrZXJDb21wb25lbnQ+O1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3llZCA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZGlzYWJsZWQgPSBmYWxzZTtcclxuXHJcbiAgQElucHV0KClcclxuICByZWFkb25seSA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHJlcXVpcmVkID0gZmFsc2U7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZGVmYXVsdFRvUHJlc2VudERhdGUgPSB0cnVlO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGFsbG93UHJldmlvdXNEYXRlcyA9IHRydWU7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgYWxsb3dGdXR1cmVEYXRlcyA9IHRydWU7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZGF0ZUZvcm1hdCA9ICdkZC9NTS95JztcclxuXHJcbiAgQElucHV0KClcclxuICBwbGFjZWhvbGRlciA9ICdEYXRlJztcclxuXHJcbiAgQElucHV0KClcclxuICBoZWxwVGV4dCA9ICdQbGVhc2Ugc2VsZWN0IGEgZGF0ZSc7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgaWNvbiA9ICdoeC1pY29uIGljb24tY2FsZW5kYXInO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGljb25QbGFjZW1lbnQgPSAncmlnaHQnO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHBsYWNlbWVudDogJ3RvcCcgfCAnYm90dG9tJyB8ICdsZWZ0JyB8ICdyaWdodCcgPSAnYm90dG9tJztcclxuXHJcbiAgQElucHV0KClcclxuICBzaG93RGVsYXkgPSB0aGlzLl9jb25maWcuc2hvd0RlbGF5O1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGhpZGVEZWxheSA9IHRoaXMuX2NvbmZpZy5oaWRlRGVsYXk7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZnJvbSA9ICcnO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHRvID0gJyc7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgaW50ZXJ2YWwgPSBmYWxzZTtcclxuXHJcbiAgQElucHV0KClcclxuICBkdWVEYXRlSW50ZXJ2YWwgPSAnMCBkYXkocyknOyAvLyAnMSB3ZWVrKHMpJyB8ICcyIG1vbnRoKHMpJyB8ICczIHllYXIocyknXHJcblxyXG4gIEBPdXRwdXQoKVxyXG4gIG9uRGF0ZUNoYW5nZTogRXZlbnRFbWl0dGVyPERhdGU+ID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPigpO1xyXG5cclxuICBwdWJsaWMgZGF0ZTogRGF0ZTtcclxuICBwdWJsaWMgdmlzaWJsZSA9IGZhbHNlO1xyXG4gIHB1YmxpYyBwcmVzZW50RGF0ZTogRGF0ZTtcclxuICBwdWJsaWMgaXNWYWxpZDogYm9vbGVhbjtcclxuICBwdWJsaWMgZGF0ZVZhbGlkYXRvcnMgPSBuZXcgQXJyYXk8KGRhdGU6IERhdGUpID0+IGJvb2xlYW4+KCk7XHJcbiAgcHJpdmF0ZSBvbkNoYW5nZWQgPSBuZXcgQXJyYXk8KHZhbHVlOiBEYXRlKSA9PiB2b2lkPigpO1xyXG4gIHByaXZhdGUgb25Ub3VjaGVkID0gbmV3IEFycmF5PCgpID0+IHZvaWQ+KCk7XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVEYXRlUmFuZ2U6IChkYXRlOiBEYXRlKSA9PiBib29sZWFuO1xyXG4gIHByaXZhdGUgX2VsZW1lbnRIdG1sUmVmOiBFbGVtZW50O1xyXG4gIHByaXZhdGUgX2VsZW1lbnRIdG1sQ29sbGVjdGlvbjogSFRNTENvbGxlY3Rpb247XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX2VsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcclxuICAgICAgICAgICAgICBwdWJsaWMgb3ZlcmxheTogT3ZlcmxheSxcclxuICAgICAgICAgICAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZSxcclxuICAgICAgICAgICAgICBwcml2YXRlIF9zY3JvbGxEaXNwYXRjaGVyOiBTY3JvbGxEaXNwYXRjaGVyLFxyXG4gICAgICAgICAgICAgIHByaXZhdGUgX2NvbXBvbmVudEZhY3RvcnlSZXNvbHZlcjogQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxyXG4gICAgICAgICAgICAgIHByaXZhdGUgX2NvbmZpZzogRGF0ZXBpY2tlckNvbmZpZyxcclxuICAgICAgICAgICAgICBAT3B0aW9uYWwoKSBwcml2YXRlIF9kaXI6IERpcmVjdGlvbmFsaXR5KSB7XHJcblxyXG4gICAgLy8gZ2V0IGlucHV0IHJlZmVyZW5jZVxyXG4gICAgdGhpcy5fZWxlbWVudEh0bWxDb2xsZWN0aW9uID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpbnB1dCcpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGlzcG9zZSB0aGUgdG9vbHRpcCB3aGVuIGRlc3Ryb3llZC5cclxuICAgKi9cclxuICBuZ09uRGVzdHJveSgpIHtcclxuICAgIGlmICh0aGlzLl9vdmVybGF5UmVmKSB7XHJcbiAgICAgIHRoaXMuX292ZXJsYXlSZWYuZGlzcG9zZSgpO1xyXG4gICAgICB0aGlzLl9jYWxlbmRhckluc3RhbmNlID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl9kZXN0cm95ZWQubmV4dCgpO1xyXG4gICAgdGhpcy5fZGVzdHJveWVkLmNvbXBsZXRlKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuXHJcbiAgICAvLyBzZXQgZWxlbWVudCByZWYgd2hpY2ggd2lsbCBiZSB1c2VkIGZvciBkcm9wZG93biBwb3NpdGlvbmluZ1xyXG4gICAgdGhpcy5fZWxlbWVudEh0bWxSZWYgPSB0aGlzLl9lbGVtZW50SHRtbENvbGxlY3Rpb24uaXRlbSgwKTtcclxuXHJcbiAgICBjb25zdCBkYXRlOiBEYXRlID0gbmV3IERhdGUoKTtcclxuICAgIHRoaXMucHJlc2VudERhdGUgPSBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSwgZGF0ZS5nZXREYXRlKCkpO1xyXG5cclxuICAgIGlmICh0aGlzLmRlZmF1bHRUb1ByZXNlbnREYXRlKSB7XHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMuc2V0RGF0ZSh0aGlzLnByZXNlbnREYXRlKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2xvc2UgdG8gdGhlIG1pbmltdW0gYW5kIG1heGl1bSBwb3NzaWJsZSBkYXRlcywgYnV0IHN0aWxsIG5vcm1hbGlzYWJsZVxyXG4gICAgLy8gaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNS4xLyNzZWMtMTUuOS4xLjFcclxuICAgIGNvbnN0IGZyb20gPSB0aGlzLnBhcnNlRGF0ZSh0aGlzLmZyb20pIHx8IG5ldyBEYXRlKC04NjMwMDAwMDAwMDAwMDAwKTtcclxuICAgIGNvbnN0IHRvID0gdGhpcy5wYXJzZURhdGUodGhpcy50bykgfHwgbmV3IERhdGUoODYzMDAwMDAwMDAwMDAwMCk7XHJcblxyXG4gICAgaWYgKCEhdGhpcy5mcm9tIHx8ICEhdGhpcy50bykge1xyXG4gICAgICB0aGlzLnZhbGlkYXRlRGF0ZVJhbmdlID0gdGhpcy5jcmVhdGVEYXRlUmFuZ2VWYWxpZGF0b3IoZnJvbSwgdG8pO1xyXG4gICAgICB0aGlzLmRhdGVWYWxpZGF0b3JzLnB1c2godGhpcy52YWxpZGF0ZURhdGVSYW5nZS5iaW5kKHRoaXMpKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXRoaXMuYWxsb3dQcmV2aW91c0RhdGVzKSB7XHJcbiAgICAgIHRoaXMuZGF0ZVZhbGlkYXRvcnMucHVzaCh0aGlzLnZhbGlkYXRlSXNOb3RCZWZvcmVEYXRlLmJpbmQodGhpcykpO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLmFsbG93RnV0dXJlRGF0ZXMpIHtcclxuICAgICAgdGhpcy5kYXRlVmFsaWRhdG9ycy5wdXNoKHRoaXMudmFsaWRhdGVJc05vdEFmdGVyRGF0ZS5iaW5kKHRoaXMpKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBzZXREYXRlKGRhdGU6IERhdGUpOiB2b2lkIHtcclxuICAgIHRoaXMuZGF0ZSA9IGRhdGU7XHJcbiAgICB0aGlzLm9uRGF0ZUNoYW5nZS5lbWl0KGRhdGUpO1xyXG4gICAgdGhpcy5wcm9wb2dhdGVDaGFuZ2UoZGF0ZSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25EYXRlU2VsZWN0RXZlbnQgPSAoaW5wdXREYXRlOiBEYXRlKTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLl9oaWRlKCk7XHJcbiAgICB0aGlzLnNldERhdGUoaW5wdXREYXRlKTtc