UNPKG

angular-nepali-datepicker

Version:

Simple Nepali datepicker component for angular applications

313 lines 34.5 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, forwardRef, Input, ViewEncapsulation } from "@angular/core"; import * as NepaliDateConverter from "nepali-date"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; import { daysMapping, monthsMapping } from "./mapping"; export class DatepickerComponent { constructor() { this.nepaliDateToday = { day: 0, month: 0, year: 0 }; this.currentNepaliDate = { day: 0, month: 0, year: 0 }; this.formattedDate = ""; this.currentDate = new Date(); this.years = []; this.daysMapping = daysMapping; this.monthsMapping = monthsMapping; this.isOpen = false; this.hideInput = false; this.alwaysVisible = false; this.language = "ne"; this.monthDisplayType = "default"; this.dayDisplayType = "default"; this.dateFormatter = (selectedDate) => { /** @type {?} */ const dd = selectedDate.day < 10 ? "0" + selectedDate.day : selectedDate.day; /** @type {?} */ const mm = selectedDate.month < 10 ? "0" + selectedDate.month : selectedDate.month; return `${dd}/${mm}/${this.selectedDate.year}`; }; this.propagateChange = (_) => { }; this.propagateTouch = (_) => { }; } /** * @return {?} */ ngOnInit() { /** @type {?} */ const nepaliDateToday = new NepaliDateConverter(new Date()); this.nepaliDateToday = { year: nepaliDateToday.getYear(), month: nepaliDateToday.getMonth(), day: nepaliDateToday.getDate() }; this.setCurrentDate(); this.populateYears(); this.setCurrentMonthData(); } /** * @return {?} */ setCurrentDate() { /** @type {?} */ let currentNepaliDate; if (!this.selectedDate) { currentNepaliDate = new NepaliDateConverter(this.currentDate); } else { const { year, month, day } = this.selectedDate; currentNepaliDate = new NepaliDateConverter(year, month, day); this.currentDate = currentNepaliDate.getEnglishDate(); } this.currentNepaliDate = { year: currentNepaliDate.getYear(), month: currentNepaliDate.getMonth(), day: currentNepaliDate.getDate() }; } /** * @return {?} */ populateYears() { for (let i = 2001; i <= 2088; i++) { this.years.push(i); } } /** * @return {?} */ resetCurrentMonthData() { this.currentMonthData = { 0: [], 1: [], 2: [], 3: [], 4: [], 5: [], 6: [] }; } /** * @return {?} */ formatValue() { if (this.selectedDate) { this.formattedDate = this.dateFormatter(this.selectedDate); } } /** * @param {?} value * @return {?} */ writeValue(value) { if (value) { this.selectedDate = value; this.currentNepaliDate = value; this.formatValue(); } } /** * @return {?} */ registerOnTouched() { } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.propagateChange = fn; } /** * @return {?} */ setCurrentMonthData() { this.resetCurrentMonthData(); // fill the currentMonthData with current date /** @type {?} */ const day = this.currentDate.getDay(); this.currentMonthData[day] = [this.currentNepaliDate.day]; // fill the currentMonthData with day before the current date this.setMonthDataBefore(day - 1, this.currentNepaliDate.day - 1); // fill the currentMonthData with day after the current date this.setMonthDataAfter(day + 1, this.currentNepaliDate.day + 1); // we need some empty spaces in place so that the dates are shown in correct order // eg if the 1st day starts on monday then we need 1 empty space for non existingn date on Sunday this.createEmptySpaces(); } /** * @param {?} day * @param {?} date * @return {?} */ setMonthDataBefore(day, date) { if (date >= 1) { if (day < 0) { day = 6; } this.currentMonthData[day] = [date, ...this.currentMonthData[day]]; this.setMonthDataBefore(--day, --date); } } /** * @param {?} day * @param {?} date * @return {?} */ setMonthDataAfter(day, date) { /** @type {?} */ const nepaliDate = new NepaliDateConverter(this.currentNepaliDate.year, this.currentNepaliDate.month, date); // only add the data if the current month matches if (nepaliDate.getMonth() === this.currentNepaliDate.month) { if (day > 6) { day = 0; } this.currentMonthData[day] = [...this.currentMonthData[day], date]; this.setMonthDataAfter(++day, ++date); } } /** * @return {?} */ createEmptySpaces() { // first find out which day has the 1st // if its a Sunday, then don't do anything else add 1 space on each previous day /** @type {?} */ let dayIndex = 0; Object.values(this.currentMonthData).find((value, index) => { if (value.includes(1)) { dayIndex = index; } return value.includes(1); }); if (dayIndex) { for (dayIndex; dayIndex > 0; dayIndex--) { /** @type {?} */ const monthData = this.currentMonthData[dayIndex - 1]; this.currentMonthData[dayIndex - 1] = [null, ...monthData]; } } } /** * @param {?} day * @return {?} */ selectDate(day) { this.selectedDate = Object.assign({}, this.currentNepaliDate, { day }); this.formatValue(); this.close(); this.propagateChange(this.selectedDate); } /** * @param {?} year * @return {?} */ selectYear(year) { this.currentNepaliDate.year = +year; /** @type {?} */ const newDate = new NepaliDateConverter(this.currentNepaliDate.year, this.currentNepaliDate.month, this.currentNepaliDate.day); this.currentDate = newDate.getEnglishDate(); this.setCurrentMonthData(); } /** * @param {?} month * @return {?} */ selectMonth(month) { this.currentNepaliDate.month = this.monthsMapping[this.language][this.monthDisplayType].indexOf(month); /** @type {?} */ const newDate = new NepaliDateConverter(this.currentNepaliDate.year, this.currentNepaliDate.month, this.currentNepaliDate.day); this.currentDate = newDate.getEnglishDate(); this.setCurrentMonthData(); } /** * @return {?} */ toggleOpen() { if (!this.alwaysVisible) { this.isOpen = !this.isOpen; } } /** * @return {?} */ open() { this.isOpen = true; } /** * @return {?} */ close() { this.isOpen = false; this.setCurrentDate(); } } DatepickerComponent.decorators = [ { type: Component, args: [{ selector: "np-datepicker", template: "<input\r\n class=\"datepicker__input\"\r\n type=\"text\"\r\n [value]=\"formattedDate | toNp: language\"\r\n [ngClass]=\"inputClass\"\r\n #origin=\"cdkOverlayOrigin\"\r\n cdk-overlay-origin\r\n (focus)=\"open()\"\r\n (keydown)=\"$event.preventDefault()\"\r\n aria-hidden=\"true\"\r\n [hidden]=\"hideInput\">\r\n<ng-template\r\n cdk-connected-overlay\r\n cdkConnectedOverlayLockPosition\r\n cdkConnectedOverlayHasBackdrop\r\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\r\n [cdkConnectedOverlayOrigin]=\"origin\"\r\n [cdkConnectedOverlayOpen]=\"isOpen\"\r\n (backdropClick)=\"close()\"\r\n (detach)=\"close()\">\r\n <ng-container [ngTemplateOutlet]=\"dp\"></ng-container>\r\n</ng-template>\r\n\r\n<ng-container [ngTemplateOutlet]=\"dp\" *ngIf=\"alwaysVisible\"></ng-container>\r\n\r\n<ng-template #dp>\r\n <div class=\"datepicker__container\">\r\n <div class=\"datepicker__options-container\">\r\n <span class=\"datepicker__options-year-container\">\r\n <span>\r\n {{'Year' | toNp : language : 'word'}}:\r\n </span>\r\n <select (change)=\"selectYear($event.target.value)\">\r\n <option\r\n *ngFor=\"let year of years\"\r\n [value]=\"year\"\r\n [selected]=\"year === currentNepaliDate?.year\">\r\n {{year | toNp: language }}\r\n </option>\r\n </select>\r\n </span>\r\n <span class=\"datepicker__options-month-container\">\r\n <span>{{'Month' | toNp : language : 'word'}}: </span>\r\n <select (change)=\"selectMonth($event.target.value)\">\r\n <option\r\n *ngFor=\"let month of monthsMapping[language][monthDisplayType]; index as i\"\r\n [value]=\"month\"\r\n [selected]=\"i === currentNepaliDate?.month\">\r\n {{month}}\r\n </option>\r\n </select>\r\n </span>\r\n </div>\r\n <div class=\"datepicker__days-container\">\r\n <div class=\"datepicker__days\" *ngFor=\"let day of daysMapping[language][dayDisplayType]; index as i\">\r\n <div class=\"datepicker__weekday\">{{day}}</div>\r\n <div class=\"datepicker__date-container\" *ngFor=\"let date of currentMonthData[i]\">\r\n <div\r\n class=\"datepicker__date\"\r\n [class.datepicker__date--active]=\"\r\n date === selectedDate?.day &&\r\n currentNepaliDate.month === selectedDate?.month &&\r\n currentNepaliDate.year === selectedDate?.year\r\n \"\r\n [class.datepicker__date--current-day]=\"\r\n date === nepaliDateToday.day &&\r\n currentNepaliDate.month === nepaliDateToday.month &&\r\n currentNepaliDate.year === nepaliDateToday.year\r\n \"\r\n [class.datepicker__date--disabled]=\"!date\"\r\n (click)=\"selectDate(date)\">\r\n <span *ngIf=\"!date\">&nbsp;</span>\r\n {{date | toNp: language }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>", providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DatepickerComponent), multi: true } ], encapsulation: ViewEncapsulation.None, styles: [".cdk-global-overlay-wrapper,.cdk-overlay-container{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1000;display:flex;max-width:100%;max-height:100%}.cdk-overlay-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:transparent;transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:1}@media screen and (-ms-high-contrast:active){.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.6}}.cdk-overlay-dark-backdrop{background:rgba(0,0,0,.32)}.cdk-overlay-transparent-backdrop,.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing{opacity:0}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}.datepicker__input{display:block}.datepicker__container{--font-family:arial,sans-serif;--font-size:14px;--container-padding:8px 5px;--container-border-color:lightgray;--container-border:1px solid;--container-background-color:white;--select-height:24px;--option-margin:0 0 7px;--option-year-container-margin:0 10px 0;--days-size:40px;--weekday-margin:0 0 5px;--active-day-color:white;--active-day-background:#27a4f7;--hover-color:#27a4f7;--selected-color:#27a4f7;display:inline-block;font-family:\"arial, sans-serif\";font-family:var(--font-family);font-size:14px;font-size:var(--font-size);padding:8px 5px;padding:var(--container-padding);border:1px solid #d3d3d3;border:var(--container-border);border-color:var(--container-border-color);background-color:#fff;background-color:var(--container-background-color)}.datepicker__options-container{margin:0 0 7px;margin:var(--option-margin)}.datepicker__options-container select{height:24px;height:var(--select-height)}.datepicker__options-year-container{display:inline-block;margin:0 10px;margin:var(--option-year-container-margin)}.datepicker__days{display:inline-block;vertical-align:top;text-align:center;width:40px;width:var(--days-size)}.datepicker__weekday{margin:0 0 5px;margin:var(--weekday-margin);font-weight:700;text-align:center}.datepicker__date{width:40px;width:var(--days-size);height:40px;height:var(--days-size);line-height:40px;line-height:var(--days-size);cursor:pointer}.datepicker__date--active{color:#fff;color:var(--active-day-color);background:#27a4f7;background:var(--active-day-background)}.datepicker__date--current-day:not(.datepicker__date--active){color:#27a4f7;color:var(--selected-color);font-weight:700}.datepicker__date--disabled{pointer-events:none}.datepicker__date:hover:not(.datepicker__date--active){color:#27a4f7;color:var(--hover-color);transition:color .3s}"] }] } ]; /** @nocollapse */ DatepickerComponent.ctorParameters = () => []; DatepickerComponent.propDecorators = { hideInput: [{ type: Input }], alwaysVisible: [{ type: Input }], inputClass: [{ type: Input }], language: [{ type: Input }], monthDisplayType: [{ type: Input }], dayDisplayType: [{ type: Input }], dateFormatter: [{ type: Input }] }; if (false) { /** @type {?} */ DatepickerComponent.prototype.nepaliDateToday; /** @type {?} */ DatepickerComponent.prototype.currentNepaliDate; /** @type {?} */ DatepickerComponent.prototype.selectedDate; /** @type {?} */ DatepickerComponent.prototype.formattedDate; /** @type {?} */ DatepickerComponent.prototype.currentDate; /** @type {?} */ DatepickerComponent.prototype.displayDate; /** @type {?} */ DatepickerComponent.prototype.years; /** @type {?} */ DatepickerComponent.prototype.currentMonthData; /** @type {?} */ DatepickerComponent.prototype.daysMapping; /** @type {?} */ DatepickerComponent.prototype.monthsMapping; /** @type {?} */ DatepickerComponent.prototype.isOpen; /** @type {?} */ DatepickerComponent.prototype.hideInput; /** @type {?} */ DatepickerComponent.prototype.alwaysVisible; /** @type {?} */ DatepickerComponent.prototype.inputClass; /** @type {?} */ DatepickerComponent.prototype.language; /** @type {?} */ DatepickerComponent.prototype.monthDisplayType; /** @type {?} */ DatepickerComponent.prototype.dayDisplayType; /** @type {?} */ DatepickerComponent.prototype.dateFormatter; /** @type {?} */ DatepickerComponent.prototype.propagateChange; /** @type {?} */ DatepickerComponent.prototype.propagateTouch; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9hbmd1bGFyLW5lcGFsaS1kYXRlcGlja2VyLyIsInNvdXJjZXMiOlsibGliL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBRVQsVUFBVSxFQUNWLEtBQUssRUFDTCxpQkFBaUIsRUFDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxLQUFLLG1CQUFtQixNQUFNLGFBQWEsQ0FBQztBQUNuRCxPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFRekUsT0FBTyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFldkQsTUFBTSxPQUFPLG1CQUFtQjtJQThDOUI7UUE3Q0Esb0JBQWUsR0FBZSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDNUQsc0JBQWlCLEdBQWUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1FBRTlELGtCQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ25CLGdCQUFXLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUl6QixVQUFLLEdBQWEsRUFBRSxDQUFDO1FBSXJCLGdCQUFXLEdBQWdCLFdBQVcsQ0FBQztRQUV2QyxrQkFBYSxHQUFpQixhQUFhLENBQUM7UUFFNUMsV0FBTSxHQUFHLEtBQUssQ0FBQztRQUdmLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFHbEIsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFNdEIsYUFBUSxHQUFnQixJQUFJLENBQUM7UUFHN0IscUJBQWdCLEdBQW1DLFNBQVMsQ0FBQztRQUc3RCxtQkFBYyxHQUF3QixTQUFTLENBQUM7UUFHaEQs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QUE0Qzs7SUFFNUMscUNBQWU7O0lBRWYsd0NBQ2tCOztJQUVsQiw0Q0FDc0I7O0lBRXRCLHlDQUNtQjs7SUFFbkIsdUNBQzZCOztJQUU3QiwrQ0FDNkQ7O0lBRTdELDZDQUNnRDs7SUFFaEQsNENBT0U7O0lBeURGLDhDQUFpQzs7SUFFakMsNkNBQWdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsXHJcbiAgT25Jbml0LFxyXG4gIGZvcndhcmRSZWYsXHJcbiAgSW5wdXQsXHJcbiAgVmlld0VuY2Fwc3VsYXRpb25cclxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xyXG5pbXBvcnQgKiBhcyBOZXBhbGlEYXRlQ29udmVydGVyIGZyb20gXCJuZXBhbGktZGF0ZVwiO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcclxuaW1wb3J0IHtcclxuICBOZXBhbGlEYXRlLFxyXG4gIE1vbnRoRGF0YSxcclxuICBEYXlzTWFwcGluZyxcclxuICBNb250aE1hcHBpbmcsXHJcbiAgRGF0ZUZvcm1hdHRlclxyXG59IGZyb20gXCIuL3R5cGVzXCI7XHJcbmltcG9ydCB7IGRheXNNYXBwaW5nLCBtb250aHNNYXBwaW5nIH0gZnJvbSBcIi4vbWFwcGluZ1wiO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6IFwibnAtZGF0ZXBpY2tlclwiLFxyXG4gIHRlbXBsYXRlVXJsOiBcIi4vZGF0ZXBpY2tlci5jb21wb25lbnQuaHRtbFwiLFxyXG4gIHN0eWxlVXJsczogW1wiLi9kYXRlcGlja2VyLmNvbXBvbmVudC5zY3NzXCJdLFxyXG4gIHByb3ZpZGVyczogW1xyXG4gICAge1xyXG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRGF0ZXBpY2tlckNvbXBvbmVudCksXHJcbiAgICAgIG11bHRpOiB0cnVlXHJcbiAgICB9XHJcbiAgXSxcclxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBEYXRlcGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciB7XHJcbiAgbmVwYWxpRGF0ZVRvZGF5OiBOZXBhbGlEYXRlID0geyBkYXk6IDAsIG1vbnRoOiAwLCB5ZWFyOiAwIH07XHJcbiAgY3VycmVudE5lcGFsaURhdGU6IE5lcGFsaURhdGUgPSB7IGRheTogMCwgbW9udGg6IDAsIHllYXI6IDAgfTtcclxuICBzZWxlY3RlZERhdGU6IE5lcGFsaURhdGU7XHJcbiAgZm9ybWF0dGVkRGF0ZSA9IFwiXCI7XHJcbiAgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpO1xyXG5cclxuICBkaXNwbGF5RGF0ZTogc3RyaW5nO1xyXG5cclxuICB5ZWFyczogbnVtYmVyW10gPSBbXTtcclxuXHJcbiAgY3VycmVudE1vbnRoRGF0YTogTW9udGhEYXRhO1xyXG5cclxuICBkYXlzTWFwcGluZzogRGF5c01hcHBpbmcgPSBkYXlzTWFwcGluZztcclxuXHJcbiAgbW9udGhzTWFwcGluZzogTW9udGhNYXBwaW5nID0gbW9udGhzTWFwcGluZztcclxuXHJcbiAgaXNPcGVuID0gZmFsc2U7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgaGlkZUlucHV0ID0gZmFsc2U7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgYWx3YXlzVmlzaWJsZSA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGlucHV0Q2xhc3M6IHN0cmluZztcclxuXHJcbiAgQElucHV0KClcclxuICBsYW5ndWFnZTogXCJlblwiIHwgXCJuZVwiID0gXCJuZVwiO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIG1vbnRoRGlzcGxheVR5cGU6IFwiZGVmYXVsdFwiIHwgXCJtb2Rlcm5cIiB8IFwic2hvcnRcIiA9IFwiZGVmYXVsdFwiO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGRheURpc3BsYXlUeXBlOiBcImRlZmF1bHRcIiB8IFwic2hvcnRcIiA9IFwiZGVmYXVsdFwiO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGRhdGVGb3JtYXR0ZXI6IERhdGVGb3JtYXR0ZXIgPSAoc2VsZWN0ZWREYXRlOiBOZXBhbGlEYXRlKSA9PiB7XHJcbiAgICBjb25zdCBkZCA9XHJcbiAgICAgIHNlbGVjdGVkRGF0ZS5kYXkgPCAxMCA/IFwiMFwiICsgc2VsZWN0ZWREYXRlLmRheSA6IHNlbGVjdGVkRGF0ZS5kYXk7XHJcbiAgICBjb25zdCBtbSA9XHJcbiAgICAgIHNlbGVjdGVkRGF0ZS5tb250aCA8IDEwID8gXCIwXCIgKyBzZWxlY3RlZERhdGUubW9udGggOiBzZWxlY3RlZERhdGUubW9udGg7XHJcbiAgICByZXR1cm4gYCR7ZGR9LyR7bW19LyR7dGhpcy5zZWxlY3RlZERhdGUueWVhcn1gO1xyXG4gIH07XHJcblxyXG4gIGNvbnN0cnVjdG9yKCkge31cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICBjb25zdCBuZXBhbGlEYXRlVG9kYXkgPSBuZXcgTmVwYWxpRGF0ZUNvbnZlcnRlcihuZXcgRGF0ZSgpKTtcclxuICAgIHRoaXMubmVwYWxpRGF0ZVRvZGF5ID0ge1xyXG4gICAgICB5ZWFyOiBuZXBhbGlEYXRlVG9kYXkuZ2V0WWVhcigpLFxyXG4gICAgICBtb250aDogbmVwYWxpRGF0ZVRvZGF5LmdldE1vbnRoKCksXHJcbiAgICAgIGRheTogbmVwYWxpRGF0ZVRvZGF5LmdldERhdGUoKVxyXG4gICAgfTtcclxuXHJcbiAgICB0aGlzLnNldEN1cnJlbnREYXRlKCk7XHJcbiAgICB0aGlzLnBvcHVsYXRlWWVhcnMoKTtcclxuICAgIHRoaXMuc2V0Q3VycmVudE1vbnRoRGF0YSgpO1xyXG4gIH1cclxuXHJcbiAgc2V0Q3VycmVudERhdGUoKSB7XHJcbiAgICBsZXQgY3VycmVudE5lcGFsaURhdGU7XHJcbiAgICBpZiAoIXRoaXMuc2VsZWN0ZWREYXRlKSB7XHJcbiAgICAgIGN1cnJlbnROZXBhbGlEYXRlID0gbmV3IE5lcGFsaURhdGVDb252ZXJ0ZXIodGhpcy5jdXJyZW50RGF0ZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zdCB7IHllYXIsIG1vbnRoLCBkYXkgfSA9IHRoaXMuc2VsZWN0ZWREYXRlO1xyXG4gICAgICBjdXJyZW50TmVwYWxpRGF0ZSA9IG5ldyBOZXBhbGlEYXRlQ29udmVydGVyKHllYXIsIG1vbnRoLCBkYXkpO1xyXG4gICAgICB0aGlzLmN1cnJlbnREYXRlID0gY3VycmVudE5lcGFsaURhdGUuZ2V0RW5nbGlzaERhdGUoKTtcclxuICAgIH1cclxuICAgIHRoaXMuY3VycmVudE5lcGFsaURhdGUgPSB7XHJcbiAgICAgIHllYXI6IGN1cnJlbnROZXBhbGlEYXRlLmdldFllYXIoKSxcclxuICAgICAgbW9udGg6IGN1cnJlbnROZXBhbGlEYXRlLmdldE1vbnRoKCksXHJcbiAgICAgIGRheTogY3VycmVudE5lcGFsaURhdGUuZ2V0RGF0ZSgpXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcG9wdWxhdGVZZWFycygpIHtcclxuICAgIGZvciAobGV0IGkgPSAyMDAxOyBpIDw9IDIwODg7IGkrKykge1xyXG4gICAgICB0aGlzLnllYXJzLnB1c2goaSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXNldEN1cnJlbnRNb250aERhdGEoKSB7XHJcbiAgICB0aGlzLmN1cnJlbnRNb250aERhdGEgPSB7XHJcbiAgICAgIDA6IFtdLFxyXG4gICAgICAxOiBbXSxcclxuICAgICAgMjogW10sXHJcbiAgICAgIDM6IFtdLFxyXG4gICAgICA0OiBbXSxcclxuICAgICAgNTogW10sXHJcbiAgICAgIDY6IFtdXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgZm9ybWF0VmFsdWUoKSB7XHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZERhdGUpIHtcclxuICAgICAgdGhpcy5mb3JtYXR0ZWREYXRlID0gdGhpcy5kYXRlRm9ybWF0dGVyKHRoaXMuc2VsZWN0ZWREYXRlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByb3BhZ2F0ZUNoYW5nZSA9IChfOiBhbnkpID0+IHt9O1xyXG5cclxuICBwcm9wYWdhdGVUb3VjaCA9IChfOiBhbnkpID0+IHt9O1xyXG5cclxuICB3cml0ZVZhbHVlKHZhbHVlOiBhbnkpIHtcclxuICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IHZhbHVlO1xyXG4gICAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlID0gdmFsdWU7XHJcbiAgICAgIHRoaXMuZm9ybWF0VmFsdWUoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKCkge31cclxuXHJcbiAgcmVnaXN0ZXJPbkNoYW5nZShmbikge1xyXG4gICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2UgPSBmbjtcclxuICB9XHJcblxyXG4gIHNldEN1cnJlbnRNb250aERhdGEoKSB7XHJcbiAgICB0aGlzLnJlc2V0Q3VycmVudE1vbnRoRGF0YSgpO1xyXG4gICAgLy8gZmlsbCB0aGUgY3VycmVudE1vbnRoRGF0YSB3aXRoIGN1cnJlbnQgZGF0ZVxyXG4gICAgY29uc3QgZGF5ID0gdGhpcy5jdXJyZW50RGF0ZS5nZXREYXkoKTtcclxuICAgIHRoaXMuY3VycmVudE1vbnRoRGF0YVtkYXldID0gW3RoaXMuY3VycmVudE5lcGFsaURhdGUuZGF5XTtcclxuXHJcbiAgICAvLyBmaWxsIHRoZSBjdXJyZW50TW9udGhEYXRhIHdpdGggZGF5IGJlZm9yZSB0aGUgY3VycmVudCBkYXRlXHJcbiAgICB0aGlzLnNldE1vbnRoRGF0YUJlZm9yZShkYXkgLSAxLCB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLmRheSAtIDEpO1xyXG5cclxuICAgIC8vIGZpbGwgdGhlIGN1cnJlbnRNb250aERhdGEgd2l0aCBkYXkgYWZ0ZXIgdGhlIGN1cnJlbnQgZGF0ZVxyXG4gICAgdGhpcy5zZXRNb250aERhdGFBZnRlcihkYXkgKyAxLCB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLmRheSArIDEpO1xyXG5cclxuICAgIC8vIHdlIG5lZWQgc29tZSBlbXB0eSBzcGFjZXMgaW4gcGxhY2Ugc28gdGhhdCB0aGUgZGF0ZXMgYXJlIHNob3duIGluIGNvcnJlY3Qgb3JkZXJcclxuICAgIC8vIGVnIGlmIHRoZSAxc3QgZGF5IHN0YXJ0cyBvbiBtb25kYXkgdGhlbiB3ZSBuZWVkIDEgZW1wdHkgc3BhY2UgZm9yIG5vbiBleGlzdGluZ24gZGF0ZSBvbiBTdW5kYXlcclxuICAgIHRoaXMuY3JlYXRlRW1wdHlTcGFjZXMoKTtcclxuICB9XHJcblxyXG4gIHNldE1vbnRoRGF0YUJlZm9yZShkYXksIGRhdGUpIHtcclxuICAgIGlmIChkYXRlID49IDEpIHtcclxuICAgICAgaWYgKGRheSA8IDApIHtcclxuICAgICAgICBkYXkgPSA2O1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuY3VycmVudE1vbnRoRGF0YVtkYXldID0gW2RhdGUsIC4uLnRoaXMuY3VycmVudE1vbnRoRGF0YVtkYXldXTtcclxuICAgICAgdGhpcy5zZXRNb250aERhdGFCZWZvcmUoLS1kYXksIC0tZGF0ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzZXRNb250aERhdGFBZnRlcihkYXksIGRhdGUpIHtcclxuICAgIGNvbnN0IG5lcGFsaURhdGUgPSBuZXcgTmVwYWxpRGF0ZUNvbnZlcnRlcihcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS55ZWFyLFxyXG4gICAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLm1vbnRoLFxyXG4gICAgICBkYXRlXHJcbiAgICApO1xyXG4gICAgLy8gIG9ubHkgYWRkIHRoZSBkYXRhIGlmIHRoZSBjdXJyZW50IG1vbnRoIG1hdGNoZXNcclxuICAgIGlmIChuZXBhbGlEYXRlLmdldE1vbnRoKCkgPT09IHRoaXMuY3VycmVudE5lcGFsaURhdGUubW9udGgpIHtcclxuICAgICAgaWYgKGRheSA+IDYpIHtcclxuICAgICAgICBkYXkgPSAwO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuY3VycmVudE1vbnRoRGF0YVtkYXldID0gWy4uLnRoaXMuY3VycmVudE1vbnRoRGF0YVtkYXldLCBkYXRlXTtcclxuICAgICAgdGhpcy5zZXRNb250aERhdGFBZnRlcigrK2RheSwgKytkYXRlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNyZWF0ZUVtcHR5U3BhY2VzKCkge1xyXG4gICAgLy8gZmlyc3QgZmluZCBvdXQgd2hpY2ggZGF5IGhhcyB0aGUgMXN0XHJcbiAgICAvLyAgaWYgaXRzIGEgU3VuZGF5LCB0aGVuIGRvbid0IGRvIGFueXRoaW5nIGVsc2UgYWRkIDEgc3BhY2Ugb24gZWFjaCBwcmV2aW91cyBkYXlcclxuICAgIGxldCBkYXlJbmRleCA9IDA7XHJcbiAgICBPYmplY3QudmFsdWVzKHRoaXMuY3VycmVudE1vbnRoRGF0YSkuZmluZCgodmFsdWUsIGluZGV4KSA9PiB7XHJcbiAgICAgIGlmICh2YWx1ZS5pbmNsdWRlcygxKSkge1xyXG4gICAgICAgIGRheUluZGV4ID0gaW5kZXg7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHZhbHVlLmluY2x1ZGVzKDEpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKGRheUluZGV4KSB7XHJcbiAgICAgIGZvciAoZGF5SW5kZXg7IGRheUluZGV4ID4gMDsgZGF5SW5kZXgtLSkge1xyXG4gICAgICAgIGNvbnN0IG1vbnRoRGF0YSA9IHRoaXMuY3VycmVudE1vbnRoRGF0YVtkYXlJbmRleCAtIDFdO1xyXG4gICAgICAgIHRoaXMuY3VycmVudE1vbnRoRGF0YVtkYXlJbmRleCAtIDFdID0gW251bGwsIC4uLm1vbnRoRGF0YV07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHNlbGVjdERhdGUoZGF5OiBudW1iZXIpIHtcclxuICAgIHRoaXMuc2VsZWN0ZWREYXRlID0geyAuLi50aGlzLmN1cnJlbnROZXBhbGlEYXRlLCBkYXkgfTtcclxuICAgIHRoaXMuZm9ybWF0VmFsdWUoKTtcclxuICAgIHRoaXMuY2xvc2UoKTtcclxuICAgIHRoaXMucHJvcGFnYXRlQ2hhbmdlKHRoaXMuc2VsZWN0ZWREYXRlKTtcclxuICB9XHJcblxyXG4gIHNlbGVjdFllYXIoeWVhcjogc3RyaW5nKSB7XHJcbiAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLnllYXIgPSAreWVhcjtcclxuICAgIGNvbnN0IG5ld0RhdGUgPSBuZXcgTmVwYWxpRGF0ZUNvbnZlcnRlcihcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS55ZWFyLFxyXG4gICAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLm1vbnRoLFxyXG4gICAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLmRheVxyXG4gICAgKTtcclxuICAgIHRoaXMuY3VycmVudERhdGUgPSBuZXdEYXRlLmdldEVuZ2xpc2hEYXRlKCk7XHJcbiAgICB0aGlzLnNldEN1cnJlbnRNb250aERhdGEoKTtcclxuICB9XHJcblxyXG4gIHNlbGVjdE1vbnRoKG1vbnRoOiBzdHJpbmcpIHtcclxuICAgIHRoaXMuY3VycmVudE5lcGFsaURhdGUubW9udGggPSB0aGlzLm1vbnRoc01hcHBpbmdbdGhpcy5sYW5ndWFnZV1bXHJcbiAgICAgIHRoaXMubW9udGhEaXNwbGF5VHlwZVxyXG4gICAgXS5pbmRleE9mKG1vbnRoKTtcclxuICAgIGNvbnN0IG5ld0RhdGUgPSBuZXcgTmVwYWxpRGF0ZUNvbnZlcnRlcihcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS55ZWFyLFxyXG4gICAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLm1vbnRoLFxyXG4gICAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLmRheVxyXG4gICAgKTtcclxuICAgIHRoaXMuY3VycmVudERhdGUgPSBuZXdEYXRlLmdldEVuZ2xpc2hEYXRlKCk7XHJcbiAgICB0aGlzLnNldEN1cnJlbnRNb250aERhdGEoKTtcclxuICB9XHJcblxyXG4gIHRvZ2dsZU9wZW4oKSB7XHJcbiAgICBpZiAoIXRoaXMuYWx3YXlzVmlzaWJsZSkge1xyXG4gICAgICB0aGlzLmlzT3BlbiA9ICF0aGlzLmlzT3BlbjtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9wZW4oKSB7XHJcbiAgICB0aGlzLmlzT3BlbiA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBjbG9zZSgpIHtcclxuICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XHJcbiAgICB0aGlzLnNldEN1cnJlbnREYXRlKCk7XHJcbiAgfVxyXG59XHJcbiJdfQ==