@asoftwareworld/form-builder-pro
Version:
ASW Form Builder Pro helps you with rapid development and designed web forms which includes several controls. The key feature of Form Builder is to make your content attractive and effective. We can customize our control at run time and preview the same b
361 lines • 61.7 kB
JavaScript
import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
import { DOCUMENT } from '@angular/common';
import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, Output, ViewEncapsulation } from '@angular/core';
import { AswDatetimepickerFilterType } from '../datetimepicker-filtertype';
import * as i0 from "@angular/core";
import * as i1 from "@asoftwareworld/form-builder-pro/common";
import * as i2 from "@angular/common";
const activeEventOptions = normalizePassiveListenerOptions({ passive: false });
export const CLOCK_RADIUS = 50;
export const CLOCK_INNER_RADIUS = 27.5;
export const CLOCK_OUTER_RADIUS = 41.25;
export const CLOCK_TICK_RADIUS = 7.0833;
/**
* A clock that is used as part of the datetimepicker.
* @docs-private
*/
export class AswClock {
_elementRef;
_adapter;
_changeDetectorRef;
_document;
/** A function used to filter which dates are selectable. */
dateFilter;
/** Step over minutes. */
interval = 1;
/** Whether the clock uses 12 hour format. */
twelvehour = false;
/** Whether the time is now in AM or PM. */
AMPM = 'AM';
/** Emits when the currently selected date changes. */
selectedChange = new EventEmitter();
/** Emits when any date is activated. */
activeDateChange = new EventEmitter();
/** Emits when any date is selected. */
_userSelection = new EventEmitter();
/** Whether the clock is in hour view. */
_hourView = true;
_hours = [];
_minutes = [];
_selectedHour;
_selectedMinute;
_timeChanged = false;
constructor(_elementRef, _adapter, _changeDetectorRef, _document) {
this._elementRef = _elementRef;
this._adapter = _adapter;
this._changeDetectorRef = _changeDetectorRef;
this._document = _document;
}
/**
* The date to display in this clock view.
*/
get activeDate() {
return this._activeDate;
}
set activeDate(value) {
const oldActiveDate = this._activeDate;
this._activeDate = this._adapter.clampDate(value, this.minDate, this.maxDate);
if (!this._adapter.sameMinute(oldActiveDate, this._activeDate)) {
this._init();
}
}
_activeDate;
/** The currently selected date. */
get selected() {
return this._selected;
}
set selected(value) {
this._selected = this._adapter.getValidDateOrNull(this._adapter.deserialize(value));
if (this._selected) {
this.activeDate = this._selected;
}
}
_selected;
/** The minimum selectable date. */
get minDate() {
return this._minDate;
}
set minDate(value) {
this._minDate = this._adapter.getValidDateOrNull(this._adapter.deserialize(value));
}
_minDate;
/** The maximum selectable date. */
get maxDate() {
return this._maxDate;
}
set maxDate(value) {
this._maxDate = this._adapter.getValidDateOrNull(this._adapter.deserialize(value));
}
_maxDate;
/** Whether the clock should be started in hour or minute view. */
set startView(value) {
this._hourView = value !== 'minute';
}
get _hand() {
const hour = this._adapter.getHour(this.activeDate);
this._selectedHour = hour;
this._selectedMinute = this._adapter.getMinute(this.activeDate);
let deg = 0;
let radius = CLOCK_OUTER_RADIUS;
if (this._hourView) {
const outer = this._selectedHour > 0 && this._selectedHour < 13;
radius = outer ? CLOCK_OUTER_RADIUS : CLOCK_INNER_RADIUS;
if (this.twelvehour) {
radius = CLOCK_OUTER_RADIUS;
}
deg = Math.round(this._selectedHour * (360 / (24 / 2)));
}
else {
deg = Math.round(this._selectedMinute * (360 / 60));
}
return {
height: `${radius}%`,
marginTop: `${50 - radius}%`,
transform: `rotate(${deg}deg)`
};
}
ngAfterContentInit() {
this.activeDate = this._activeDate || this._adapter.today();
this._init();
}
ngOnDestroy() {
this._removeGlobalEvents();
}
ngOnChanges() {
this._init();
}
/** Called when the user has put their pointer down on the clock. */
_pointerDown = (event) => {
this._timeChanged = false;
this.setTime(event);
this._bindGlobalEvents(event);
};
/**
* Called when the user has moved their pointer after
* starting to drag. Bound on the document level.
*/
_pointerMove = (event) => {
if (event.cancelable) {
event.preventDefault();
}
this.setTime(event);
};
/** Called when the user has lifted their pointer. Bound on the document level. */
_pointerUp = (event) => {
if (event.cancelable) {
event.preventDefault();
}
this._removeGlobalEvents();
if (this._timeChanged) {
this.selectedChange.emit(this.activeDate);
if (!this._hourView) {
this._userSelection.emit();
}
}
};
/** Binds our global move and end events. */
_bindGlobalEvents(triggerEvent) {
// Note that we bind the events to the `document`, because it allows us to capture
// drag cancel events where the user's pointer is outside the browser window.
const document = this._document;
const isTouch = isTouchEvent(triggerEvent);
const moveEventName = isTouch ? 'touchmove' : 'mousemove';
const endEventName = isTouch ? 'touchend' : 'mouseup';
document.addEventListener(moveEventName, this._pointerMove, activeEventOptions);
document.addEventListener(endEventName, this._pointerUp, activeEventOptions);
if (isTouch) {
document.addEventListener('touchcancel', this._pointerUp, activeEventOptions);
}
}
/** Removes any global event listeners that we may have added. */
_removeGlobalEvents() {
const document = this._document;
document.removeEventListener('mousemove', this._pointerMove, activeEventOptions);
document.removeEventListener('mouseup', this._pointerUp, activeEventOptions);
document.removeEventListener('touchmove', this._pointerMove, activeEventOptions);
document.removeEventListener('touchend', this._pointerUp, activeEventOptions);
document.removeEventListener('touchcancel', this._pointerUp, activeEventOptions);
}
/** Initializes this clock view. */
_init() {
this._hours.length = 0;
this._minutes.length = 0;
const hourNames = this._adapter.getHourNames();
const minuteNames = this._adapter.getMinuteNames();
if (this.twelvehour) {
const hours = [];
for (let i = 0; i < hourNames.length; i++) {
const radian = (i / 6) * Math.PI;
const radius = CLOCK_OUTER_RADIUS;
const hour = i;
const date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), hour, 0);
// Check if the date is enabled, no need to respect the minute setting here
const enabled = (!this.minDate || this._adapter.compareDatetime(date, this.minDate, false) >= 0) &&
(!this.maxDate || this._adapter.compareDatetime(date, this.maxDate, false) <= 0) &&
(!this.dateFilter || this.dateFilter(date, AswDatetimepickerFilterType.HOUR));
// display value for twelvehour clock should be from 1-12 not including 0 and not above 12
hours.push({
value: i,
displayValue: i % 12 === 0 ? '12' : hourNames[i % 12],
enabled,
top: CLOCK_RADIUS - Math.cos(radian) * radius - CLOCK_TICK_RADIUS,
left: CLOCK_RADIUS + Math.sin(radian) * radius - CLOCK_TICK_RADIUS
});
}
// filter out AM or PM hours based on AMPM
if (this.AMPM === 'AM') {
this._hours = hours.filter((x) => x.value < 12);
}
else {
this._hours = hours.filter((x) => x.value >= 12);
}
}
else {
for (let i = 0; i < hourNames.length; i++) {
const radian = (i / 6) * Math.PI;
const outer = i > 0 && i < 13;
const radius = outer ? CLOCK_OUTER_RADIUS : CLOCK_INNER_RADIUS;
const date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), i, 0);
// Check if the date is enabled, no need to respect the minute setting here
const enabled = (!this.minDate || this._adapter.compareDatetime(date, this.minDate, false) >= 0) &&
(!this.maxDate || this._adapter.compareDatetime(date, this.maxDate, false) <= 0) &&
(!this.dateFilter || this.dateFilter(date, AswDatetimepickerFilterType.HOUR));
this._hours.push({
value: i,
displayValue: i === 0 ? '00' : hourNames[i],
enabled,
top: CLOCK_RADIUS - Math.cos(radian) * radius - CLOCK_TICK_RADIUS,
left: CLOCK_RADIUS + Math.sin(radian) * radius - CLOCK_TICK_RADIUS,
fontSize: i > 0 && i < 13 ? '' : '80%'
});
}
}
for (let i = 0; i < minuteNames.length; i += 5) {
const radian = (i / 30) * Math.PI;
const date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), this._adapter.getHour(this.activeDate), i);
const enabled = (!this.minDate || this._adapter.compareDatetime(date, this.minDate) >= 0) &&
(!this.maxDate || this._adapter.compareDatetime(date, this.maxDate) <= 0) &&
(!this.dateFilter || this.dateFilter(date, AswDatetimepickerFilterType.MINUTE));
this._minutes.push({
value: i,
displayValue: i === 0 ? '00' : minuteNames[i],
enabled,
top: CLOCK_RADIUS - Math.cos(radian) * CLOCK_OUTER_RADIUS - CLOCK_TICK_RADIUS,
left: CLOCK_RADIUS + Math.sin(radian) * CLOCK_OUTER_RADIUS - CLOCK_TICK_RADIUS
});
}
}
/**
* Set Time
* @param event
*/
setTime(event) {
const trigger = this._elementRef.nativeElement;
const triggerRect = trigger.getBoundingClientRect();
const width = trigger.offsetWidth;
const height = trigger.offsetHeight;
const { pageX, pageY } = getPointerPositionOnPage(event);
const x = width / 2 - (pageX - triggerRect.left - window.pageXOffset);
const y = height / 2 - (pageY - triggerRect.top - window.pageYOffset);
let radian = Math.atan2(-x, y);
const unit = Math.PI / (this._hourView ? 6 : this.interval ? 30 / this.interval : 30);
const z = Math.sqrt(x * x + y * y);
const outer = this._hourView && z > (width * (CLOCK_OUTER_RADIUS / 100) + width * (CLOCK_INNER_RADIUS / 100)) / 2;
if (radian < 0) {
radian = Math.PI * 2 + radian;
}
let value = Math.round(radian / unit);
let date;
if (this._hourView) {
if (this.twelvehour) {
if (this.AMPM === 'AM') {
value = value === 0 ? 12 : value;
}
else {
// if we chosen 12 in PM, the value should be 0 for 0:00,
// else we can safely add 12 to the final value
value = value === 12 ? 0 : value + 12;
}
}
else {
if (value === 12) {
value = 0;
}
value = outer ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12;
}
date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), value, this._adapter.getMinute(this.activeDate));
}
else {
if (this.interval) {
value *= this.interval;
}
if (value === 60) {
value = 0;
}
date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), this._adapter.getHour(this.activeDate), value);
}
this._timeChanged = true;
this.activeDate = date;
this._changeDetectorRef.markForCheck();
this.activeDateChange.emit(this.activeDate);
}
static ngAcceptInputType_twelvehour;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswClock, deps: [{ token: i0.ElementRef }, { token: i1.DatetimeAdapter }, { token: i0.ChangeDetectorRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: AswClock, selector: "asw-clock", inputs: { dateFilter: "dateFilter", interval: "interval", twelvehour: "twelvehour", AMPM: "AMPM", activeDate: "activeDate", selected: "selected", minDate: "minDate", maxDate: "maxDate", startView: "startView" }, outputs: { selectedChange: "selectedChange", activeDateChange: "activeDateChange", _userSelection: "_userSelection" }, host: { attributes: { "role": "clock" }, listeners: { "mousedown": "_pointerDown($event)", "touchstart": "_pointerDown($event)" }, classAttribute: "asw-clock" }, exportAs: ["aswClock"], usesOnChanges: true, ngImport: i0, template: "<div class=\"asw-clock-wrapper\">\r\n <div class=\"asw-clock-center\"></div>\r\n <div class=\"asw-clock-hand\" [ngStyle]=\"_hand\"></div>\r\n <div class=\"asw-clock-hours\" [class.active]=\"_hourView\">\r\n <div *ngFor=\"let item of _hours\"\r\n class=\"asw-clock-cell\"\r\n [class.asw-clock-cell-disabled]=\"!item.enabled\"\r\n [class.asw-clock-cell-selected]=\"_selectedHour === item.value\"\r\n [style.fontSize]=\"item.fontSize\"\r\n [style.left]=\"item.left+'%'\"\r\n [style.top]=\"item.top+'%'\">{{ item.displayValue }}\r\n </div>\r\n </div>\r\n <div class=\"asw-clock-minutes\" [class.active]=\"!_hourView\">\r\n <div *ngFor=\"let item of _minutes\"\r\n class=\"asw-clock-cell\"\r\n [class.asw-clock-cell-disabled]=\"!item.enabled\"\r\n [class.asw-clock-cell-selected]=\"_selectedMinute === item.value\"\r\n [style.left]=\"item.left+'%'\"\r\n [style.top]=\"item.top+'%'\">{{ item.displayValue }}\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".asw-clock{position:relative;display:block;min-width:224px;margin:12px;box-sizing:border-box;-webkit-user-select:none;user-select:none;touch-action:none}.asw-clock-wrapper{position:relative;width:100%;height:0;padding-top:100%;border-radius:50%}.asw-clock-center{position:absolute;top:50%;left:50%;width:2%;height:2%;margin:-1%;border-radius:50%}.asw-clock-hand{position:absolute;inset:0;width:1px;margin:0 auto;transform-origin:bottom}.asw-clock-hand:before{content:\"\";position:absolute;top:-4px;left:-4px;width:8px;height:8px;border-radius:50%}.asw-clock-hours,.asw-clock-minutes{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;visibility:hidden;transition:.35s;transform:scale(1.2)}.asw-clock-hours.active,.asw-clock-minutes.active{opacity:1;visibility:visible;transform:scale(1)}.asw-clock-minutes{transform:scale(.8)}.asw-clock-cell{position:absolute;display:flex;width:14.1666%;height:14.1666%;justify-content:center;box-sizing:border-box;border-radius:50%;align-items:center;cursor:pointer}.asw-clock-cell.asw-clock-cell-disabled{pointer-events:none}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswClock, decorators: [{
type: Component,
args: [{ selector: 'asw-clock', host: {
role: 'clock',
class: 'asw-clock',
'(mousedown)': '_pointerDown($event)',
'(touchstart)': '_pointerDown($event)'
}, exportAs: 'aswClock', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"asw-clock-wrapper\">\r\n <div class=\"asw-clock-center\"></div>\r\n <div class=\"asw-clock-hand\" [ngStyle]=\"_hand\"></div>\r\n <div class=\"asw-clock-hours\" [class.active]=\"_hourView\">\r\n <div *ngFor=\"let item of _hours\"\r\n class=\"asw-clock-cell\"\r\n [class.asw-clock-cell-disabled]=\"!item.enabled\"\r\n [class.asw-clock-cell-selected]=\"_selectedHour === item.value\"\r\n [style.fontSize]=\"item.fontSize\"\r\n [style.left]=\"item.left+'%'\"\r\n [style.top]=\"item.top+'%'\">{{ item.displayValue }}\r\n </div>\r\n </div>\r\n <div class=\"asw-clock-minutes\" [class.active]=\"!_hourView\">\r\n <div *ngFor=\"let item of _minutes\"\r\n class=\"asw-clock-cell\"\r\n [class.asw-clock-cell-disabled]=\"!item.enabled\"\r\n [class.asw-clock-cell-selected]=\"_selectedMinute === item.value\"\r\n [style.left]=\"item.left+'%'\"\r\n [style.top]=\"item.top+'%'\">{{ item.displayValue }}\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".asw-clock{position:relative;display:block;min-width:224px;margin:12px;box-sizing:border-box;-webkit-user-select:none;user-select:none;touch-action:none}.asw-clock-wrapper{position:relative;width:100%;height:0;padding-top:100%;border-radius:50%}.asw-clock-center{position:absolute;top:50%;left:50%;width:2%;height:2%;margin:-1%;border-radius:50%}.asw-clock-hand{position:absolute;inset:0;width:1px;margin:0 auto;transform-origin:bottom}.asw-clock-hand:before{content:\"\";position:absolute;top:-4px;left:-4px;width:8px;height:8px;border-radius:50%}.asw-clock-hours,.asw-clock-minutes{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;visibility:hidden;transition:.35s;transform:scale(1.2)}.asw-clock-hours.active,.asw-clock-minutes.active{opacity:1;visibility:visible;transform:scale(1)}.asw-clock-minutes{transform:scale(.8)}.asw-clock-cell{position:absolute;display:flex;width:14.1666%;height:14.1666%;justify-content:center;box-sizing:border-box;border-radius:50%;align-items:center;cursor:pointer}.asw-clock-cell.asw-clock-cell-disabled{pointer-events:none}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.DatetimeAdapter }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }], propDecorators: { dateFilter: [{
type: Input
}], interval: [{
type: Input
}], twelvehour: [{
type: Input
}], AMPM: [{
type: Input
}], selectedChange: [{
type: Output
}], activeDateChange: [{
type: Output
}], _userSelection: [{
type: Output
}], activeDate: [{
type: Input
}], selected: [{
type: Input
}], minDate: [{
type: Input
}], maxDate: [{
type: Input
}], startView: [{
type: Input
}] } });
/** Returns whether an event is a touch event. */
function isTouchEvent(event) {
// This function is called for every pixel that the user has dragged so we need it to be
// as fast as possible. Since we only bind mouse events and touch events, we can assume
// that if the event's name starts with `t`, it's a touch event.
return event.type[0] === 't';
}
/** Gets the coordinates of a touch or mouse event relative to the document. */
function getPointerPositionOnPage(event) {
let point;
if (isTouchEvent(event)) {
// `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
point = event.touches[0] || event.changedTouches[0];
}
else {
point = event;
}
return point;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9kYXRldGltZXBpY2tlci9jbG9jay9jbG9jay50cyIsIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2RhdGV0aW1lcGlja2VyL2Nsb2NrL2Nsb2NrLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFBb0IsdUJBQXVCLEVBQXFCLFNBQVMsRUFBYyxZQUFZLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBd0IsTUFBTSxFQUFpQixpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVqTixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQzs7OztBQUczRSxNQUFNLGtCQUFrQixHQUFHLCtCQUErQixDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7QUFFL0UsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQUMvQixNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUM7QUFDdkMsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsS0FBSyxDQUFDO0FBQ3hDLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztBQUt4Qzs7O0dBR0c7QUFlSCxNQUFNLE9BQU8sUUFBUTtJQW9DTDtJQUNBO0lBQ0E7SUFDa0I7SUF0QzlCLDREQUE0RDtJQUNuRCxVQUFVLENBQTJEO0lBRTlFLHlCQUF5QjtJQUNoQixRQUFRLEdBQVcsQ0FBQyxDQUFDO0lBRTlCLDZDQUE2QztJQUNwQyxVQUFVLEdBQVksS0FBSyxDQUFDO0lBRXJDLDJDQUEyQztJQUNsQyxJQUFJLEdBQVksSUFBSSxDQUFDO0lBRTlCLHNEQUFz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QztTQUFNLENBQUM7UUFDSixLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ2xCLENBQUM7SUFFRCxPQUFPLEtBQUssQ0FBQztBQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQm9vbGVhbklucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcbmltcG9ydCB7IG5vcm1hbGl6ZVBhc3NpdmVMaXN0ZW5lck9wdGlvbnMgfSBmcm9tICdAYW5ndWxhci9jZGsvcGxhdGZvcm0nO1xuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQWZ0ZXJDb250ZW50SW5pdCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5qZWN0LCBJbnB1dCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE91dHB1dCwgU2ltcGxlQ2hhbmdlcywgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERhdGV0aW1lQWRhcHRlciB9IGZyb20gJ0Bhc29mdHdhcmV3b3JsZC9mb3JtLWJ1aWxkZXItcHJvL2NvbW1vbic7XG5pbXBvcnQgeyBBc3dEYXRldGltZXBpY2tlckZpbHRlclR5cGUgfSBmcm9tICcuLi9kYXRldGltZXBpY2tlci1maWx0ZXJ0eXBlJztcbmltcG9ydCB7IEFzd0FNUE0gfSBmcm9tICcuLi9kYXRldGltZXBpY2tlci10eXBlcyc7XG5cbmNvbnN0IGFjdGl2ZUV2ZW50T3B0aW9ucyA9IG5vcm1hbGl6ZVBhc3NpdmVMaXN0ZW5lck9wdGlvbnMoeyBwYXNzaXZlOiBmYWxzZSB9KTtcblxuZXhwb3J0IGNvbnN0IENMT0NLX1JBRElVUyA9IDUwO1xuZXhwb3J0IGNvbnN0IENMT0NLX0lOTkVSX1JBRElVUyA9IDI3LjU7XG5leHBvcnQgY29uc3QgQ0xPQ0tfT1VURVJfUkFESVVTID0gNDEuMjU7XG5leHBvcnQgY29uc3QgQ0xPQ0tfVElDS19SQURJVVMgPSA3LjA4MzM7XG5cbi8qKiBQb3NzaWJsZSB2aWV3cyBmb3IgZGF0ZXRpbWVwaWNrZXIgY2xvY2suICovXG5leHBvcnQgdHlwZSBBc3dDbG9ja1ZpZXcgPSAnaG91cicgfCAnbWludXRlJztcblxuLyoqXG4gKiBBIGNsb2NrIHRoYXQgaXMgdXNlZCBhcyBwYXJ0IG9mIHRoZSBkYXRldGltZXBpY2tlci5cbiAqIEBkb2NzLXByaXZhdGVcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdhc3ctY2xvY2snLFxuICAgIHRlbXBsYXRlVXJsOiAnY2xvY2suaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJ2Nsb2NrLnNjc3MnXSxcbiAgICBob3N0OiB7XG4gICAgICAgIHJvbGU6ICdjbG9jaycsXG4gICAgICAgIGNsYXNzOiAnYXN3LWNsb2NrJyxcbiAgICAgICAgJyhtb3VzZWRvd24pJzogJ19wb2ludGVyRG93bigkZXZlbnQpJyxcbiAgICAgICAgJyh0b3VjaHN0YXJ0KSc6ICdfcG9pbnRlckRvd24oJGV2ZW50KSdcbiAgICB9LFxuICAgIGV4cG9ydEFzOiAnYXN3Q2xvY2snLFxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgQXN3Q2xvY2s8RD4gaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XG4gICAgLyoqIEEgZnVuY3Rpb24gdXNlZCB0byBmaWx0ZXIgd2hpY2ggZGF0ZXMgYXJlIHNlbGVjdGFibGUuICovXG4gICAgQElucHV0KCkgZGF0ZUZpbHRlciE6IChkYXRlOiBELCB0eXBlOiBBc3dEYXRldGltZXBpY2tlckZpbHRlclR5cGUpID0+IGJvb2xlYW47XG5cbiAgICAvKiogU3RlcCBvdmVyIG1pbnV0ZXMuICovXG4gICAgQElucHV0KCkgaW50ZXJ2YWw6IG51bWJlciA9IDE7XG5cbiAgICAvKiogV2hldGhlciB0aGUgY2xvY2sgdXNlcyAxMiBob3VyIGZvcm1hdC4gKi9cbiAgICBASW5wdXQoKSB0d2VsdmVob3VyOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogV2hldGhlciB0aGUgdGltZSBpcyBub3cgaW4gQU0gb3IgUE0uICovXG4gICAgQElucHV0KCkgQU1QTTogQXN3QU1QTSA9ICdBTSc7XG5cbiAgICAvKiogRW1pdHMgd2hlbiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIGRhdGUgY2hhbmdlcy4gKi9cbiAgICBAT3V0cHV0KCkgc2VsZWN0ZWRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEQ+KCk7XG5cbiAgICAvKiogRW1pdHMgd2hlbiBhbnkgZGF0ZSBpcyBhY3RpdmF0ZWQuICovXG4gICAgQE91dHB1dCgpIGFjdGl2ZURhdGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEQ+KCk7XG5cbiAgICAvKiogRW1pdHMgd2hlbiBhbnkgZGF0ZSBpcyBzZWxlY3RlZC4gKi9cbiAgICBAT3V0cHV0KCkgcmVhZG9ubHkgX3VzZXJTZWxlY3Rpb24gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgICAvKiogV2hldGhlciB0aGUgY2xvY2sgaXMgaW4gaG91ciB2aWV3LiAqL1xuICAgIF9ob3VyVmlldzogYm9vbGVhbiA9IHRydWU7XG5cbiAgICBfaG91cnM6IGFueVtdID0gW107XG5cbiAgICBfbWludXRlczogYW55W10gPSBbXTtcblxuICAgIF9zZWxlY3RlZEhvdXIhOiBudW1iZXI7XG5cbiAgICBfc2VsZWN0ZWRNaW51dGUhOiBudW1iZXI7XG5cbiAgICBwcml2YXRlIF90aW1lQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgX2VsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgICAgIHByaXZhdGUgX2FkYXB0ZXI6IERhdGV0aW1lQWRhcHRlcjxEPixcbiAgICAgICAgcHJpdmF0ZSBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIF9kb2N1bWVudDogYW55XG4gICAgKSB7fVxuXG4gICAgLyoqXG4gICAgICogVGhlIGRhdGUgdG8gZGlzcGxheSBpbiB0aGlzIGNsb2NrIHZpZXcuXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBnZXQgYWN0aXZlRGF0ZSgpOiBEIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FjdGl2ZURhdGU7XG4gICAgfVxuICAgIHNldCBhY3RpdmVEYXRlKHZhbHVlOiBEKSB7XG4gICAgICAgIGNvbnN0IG9sZEFjdGl2ZURhdGUgPSB0aGlzLl9hY3RpdmVEYXRlO1xuICAgICAgICB0aGlzLl9hY3RpdmVEYXRlID0gdGhpcy5fYWRhcHRlci5jbGFtcERhdGUodmFsdWUsIHRoaXMubWluRGF0ZSwgdGhpcy5tYXhEYXRlKTtcbiAgICAgICAgaWYgKCF0aGlzLl9hZGFwdGVyLnNhbWVNaW51dGUob2xkQWN0aXZlRGF0ZSwgdGhpcy5fYWN0aXZlRGF0ZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX2luaXQoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBwcml2YXRlIF9hY3RpdmVEYXRlITogRDtcblxuICAgIC8qKiBUaGUgY3VycmVudGx5IHNlbGVjdGVkIGRhdGUuICovXG4gICAgQElucHV0KClcbiAgICBnZXQgc2VsZWN0ZWQoKTogRCB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2VsZWN0ZWQ7XG4gICAgfVxuICAgIHNldCBzZWxlY3RlZCh2YWx1ZTogRCB8IG51bGwpIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWQgPSB0aGlzLl9hZGFwdGVyLmdldFZhbGlkRGF0ZU9yTnVsbCh0aGlzLl9hZGFwdGVyLmRlc2VyaWFsaXplKHZhbHVlKSk7XG4gICAgICAgIGlmICh0aGlzLl9zZWxlY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmVEYXRlID0gdGhpcy5fc2VsZWN0ZWQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcHJpdmF0ZSBfc2VsZWN0ZWQhOiBEIHwgbnVsbDtcblxuICAgIC8qKiBUaGUgbWluaW11bSBzZWxlY3RhYmxlIGRhdGUuICovXG4gICAgQElucHV0KClcbiAgICBnZXQgbWluRGF0ZSgpOiBEIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9taW5EYXRlO1xuICAgIH1cbiAgICBzZXQgbWluRGF0ZSh2YWx1ZTogRCB8IG51bGwpIHtcbiAgICAgICAgdGhpcy5fbWluRGF0ZSA9IHRoaXMuX2FkYXB0ZXIuZ2V0VmFsaWREYXRlT3JOdWxsKHRoaXMuX2FkYXB0ZXIuZGVzZXJpYWxpemUodmFsdWUpKTtcbiAgICB9XG4gICAgcHJpdmF0ZSBfbWluRGF0ZSE6IEQgfCBudWxsO1xuXG4gICAgLyoqIFRoZSBtYXhpbXVtIHNlbGVjdGFibGUgZGF0ZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBtYXhEYXRlKCk6IEQgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21heERhdGU7XG4gICAgfVxuICAgIHNldCBtYXhEYXRlKHZhbHVlOiBEIHwgbnVsbCkge1xuICAgICAgICB0aGlzLl9tYXhEYXRlID0gdGhpcy5fYWRhcHRlci5nZXRWYWxpZERhdGVPck51bGwodGhpcy5fYWRhcHRlci5kZXNlcmlhbGl6ZSh2YWx1ZSkpO1xuICAgIH1cbiAgICBwcml2YXRlIF9tYXhEYXRlITogRCB8IG51bGw7XG5cbiAgICAvKiogV2hldGhlciB0aGUgY2xvY2sgc2hvdWxkIGJlIHN0YXJ0ZWQgaW4gaG91ciBvciBtaW51dGUgdmlldy4gKi9cbiAgICBASW5wdXQoKVxuICAgIHNldCBzdGFydFZpZXcodmFsdWU6IEFzd0Nsb2NrVmlldykge1xuICAgICAgICB0aGlzLl9ob3VyVmlldyA9IHZhbHVlICE9PSAnbWludXRlJztcbiAgICB9XG5cbiAgICBnZXQgX2hhbmQoKSB7XG4gICAgICAgIGNvbnN0IGhvdXIgPSB0aGlzLl9hZGFwdGVyLmdldEhvdXIodGhpcy5hY3RpdmVEYXRlKTtcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWRIb3VyID0gaG91cjtcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWRNaW51dGUgPSB0aGlzLl9hZGFwdGVyLmdldE1pbnV0ZSh0aGlzLmFjdGl2ZURhdGUpO1xuICAgICAgICBsZXQgZGVnID0gMDtcbiAgICAgICAgbGV0IHJhZGl1cyA9IENMT0NLX09VVEVSX1JBRElVUztcbiAgICAgICAgaWYgKHRoaXMuX2hvdXJWaWV3KSB7XG4gICAgICAgICAgICBjb25zdCBvdXRlciA9IHRoaXMuX3NlbGVjdGVkSG91ciA+IDAgJiYgdGhpcy5fc2VsZWN0ZWRIb3VyIDwgMTM7XG4gICAgICAgICAgICByYWRpdXMgPSBvdXRlciA/IENMT0NLX09VVEVSX1JBRElVUyA6IENMT0NLX0lOTkVSX1JBRElVUztcbiAgICAgICAgICAgIGlmICh0aGlzLnR3ZWx2ZWhvdXIpIHtcbiAgICAgICAgICAgICAgICByYWRpdXMgPSBDTE9DS19PVVRFUl9SQURJVVM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWcgPSBNYXRoLnJvdW5kKHRoaXMuX3NlbGVjdGVkSG91ciAqICgzNjAgLyAoMjQgLyAyKSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVnID0gTWF0aC5yb3VuZCh0aGlzLl9zZWxlY3RlZE1pbnV0ZSAqICgzNjAgLyA2MCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoZWlnaHQ6IGAke3JhZGl1c30lYCxcbiAgICAgICAgICAgIG1hcmdpblRvcDogYCR7NTAgLSByYWRpdXN9JWAsXG4gICAgICAgICAgICB0cmFuc2Zvcm06IGByb3RhdGUoJHtkZWd9ZGVnKWBcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XG4gICAgICAgIHRoaXMuYWN0aXZlRGF0ZSA9IHRoaXMuX2FjdGl2ZURhdGUgfHwgdGhpcy5fYWRhcHRlci50b2RheSgpO1xuICAgICAgICB0aGlzLl9pbml0KCk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuX3JlbW92ZUdsb2JhbEV2ZW50cygpO1xuICAgIH1cblxuICAgIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9pbml0KCk7XG4gICAgfVxuXG4gICAgLyoqIENhbGxlZCB3aGVuIHRoZSB1c2VyIGhhcyBwdXQgdGhlaXIgcG9pbnRlciBkb3duIG9uIHRoZSBjbG9jay4gKi9cbiAgICBwcml2YXRlIF9wb2ludGVyRG93biA9IChldmVudDogVG91Y2hFdmVudCB8IE1vdXNlRXZlbnQpID0+IHtcbiAgICAgICAgdGhpcy5fdGltZUNoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zZXRUaW1lKGV2ZW50KTtcbiAgICAgICAgdGhpcy5fYmluZEdsb2JhbEV2ZW50cyhldmVudCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENhbGxlZCB3aGVuIHRoZSB1c2VyIGhhcyBtb3ZlZCB0aGVpciBwb2ludGVyIGFmdGVyXG4gICAgICogc3RhcnRpbmcgdG8gZHJhZy4gQm91bmQgb24gdGhlIGRvY3VtZW50IGxldmVsLlxuICAgICAqL1xuICAgIHByaXZhdGUgX3BvaW50ZXJNb3ZlID0gKGV2ZW50OiBUb3VjaEV2ZW50IHwgTW91c2VFdmVudCkgPT4ge1xuICAgICAgICBpZiAoZXZlbnQuY2FuY2VsYWJsZSkge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldFRpbWUoZXZlbnQpO1xuICAgIH07XG5cbiAgICAvKiogQ2FsbGVkIHdoZW4gdGhlIHVzZXIgaGFzIGxpZnRlZCB0aGVpciBwb2ludGVyLiBCb3VuZCBvbiB0aGUgZG9jdW1lbnQgbGV2ZWwuICovXG4gICAgcHJpdmF0ZSBfcG9pbnRlclVwID0gKGV2ZW50OiBUb3VjaEV2ZW50IHwgTW91c2VFdmVudCkgPT4ge1xuICAgICAgICBpZiAoZXZlbnQuY2FuY2VsYWJsZSkge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9yZW1vdmVHbG9iYWxFdmVudHMoKTtcblxuICAgICAgICBpZiAodGhpcy5fdGltZUNoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRDaGFuZ2UuZW1pdCh0aGlzLmFjdGl2ZURhdGUpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9ob3VyVmlldykge1xuICAgICAgICAgICAgICAgIHRoaXMuX3VzZXJTZWxlY3Rpb24uZW1pdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKiBCaW5kcyBvdXIgZ2xvYmFsIG1vdmUgYW5kIGVuZCBldmVudHMuICovXG4gICAgcHJpdmF0ZSBfYmluZEdsb2JhbEV2ZW50cyh0cmlnZ2VyRXZlbnQ6IFRvdWNoRXZlbnQgfCBNb3VzZUV2ZW50KSB7XG4gICAgICAgIC8vIE5vdGUgdGhhdCB3ZSBiaW5kIHRoZSBldmVudHMgdG8gdGhlIGBkb2N1bWVudGAsIGJlY2F1c2UgaXQgYWxsb3dzIHVzIHRvIGNhcHR1cmVcbiAgICAgICAgLy8gZHJhZyBjYW5jZWwgZXZlbnRzIHdoZXJlIHRoZSB1c2VyJ3MgcG9pbnRlciBpcyBvdXRzaWRlIHRoZSBicm93c2VyIHdpbmRvdy5cbiAgICAgICAgY29uc3QgZG9jdW1lbnQgPSB0aGlzLl9kb2N1bWVudDtcbiAgICAgICAgY29uc3QgaXNUb3VjaCA9IGlzVG91Y2hFdmVudCh0cmlnZ2VyRXZlbnQpO1xuICAgICAgICBjb25zdCBtb3ZlRXZlbnROYW1lID0gaXNUb3VjaCA/ICd0b3VjaG1vdmUnIDogJ21vdXNlbW92ZSc7XG4gICAgICAgIGNvbnN0IGVuZEV2ZW50TmFtZSA9IGlzVG91Y2ggPyAndG91Y2hlbmQnIDogJ21vdXNldXAnO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKG1vdmVFdmVudE5hbWUsIHRoaXMuX3BvaW50ZXJNb3ZlLCBhY3RpdmVFdmVudE9wdGlvbnMpO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGVuZEV2ZW50TmFtZSwgdGhpcy5fcG9pbnRlclVwLCBhY3RpdmVFdmVudE9wdGlvbnMpO1xuXG4gICAgICAgIGlmIChpc1RvdWNoKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGNhbmNlbCcsIHRoaXMuX3BvaW50ZXJVcCwgYWN0aXZlRXZlbnRPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBSZW1vdmVzIGFueSBnbG9iYWwgZXZlbnQgbGlzdGVuZXJzIHRoYXQgd2UgbWF5IGhhdmUgYWRkZWQuICovXG4gICAgcHJpdmF0ZSBfcmVtb3ZlR2xvYmFsRXZlbnRzKCkge1xuICAgICAgICBjb25zdCBkb2N1bWVudCA9IHRoaXMuX2RvY3VtZW50O1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9wb2ludGVyTW92ZSwgYWN0aXZlRXZlbnRPcHRpb25zKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX3BvaW50ZXJVcCwgYWN0aXZlRXZlbnRPcHRpb25zKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fcG9pbnRlck1vdmUsIGFjdGl2ZUV2ZW50T3B0aW9ucyk7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fcG9pbnRlclVwLCBhY3RpdmVFdmVudE9wdGlvbnMpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGNhbmNlbCcsIHRoaXMuX3BvaW50ZXJVcCwgYWN0aXZlRXZlbnRPcHRpb25zKTtcbiAgICB9XG5cbiAgICAvKiogSW5pdGlhbGl6ZXMgdGhpcyBjbG9jayB2aWV3LiAqL1xuICAgIHByaXZhdGUgX2luaXQoKSB7XG4gICAgICAgIHRoaXMuX2hvdXJzLmxlbmd0aCA