materialize-angular
Version:
Material UI Angular library
387 lines • 34.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* Generated from: app/completed-components/calendar/calendar.component.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @license
* Copyright Workylab. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://raw.githubusercontent.com/workylab/materialize-angular/master/LICENSE
*/
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { config } from '../../config';
import { days } from '../../fixtures/calendar-week-days';
import { months } from '../../fixtures/calendar-months';
export class CalendarComponent {
constructor() {
this.className = CalendarComponent.defaultProps.className;
this.date = CalendarComponent.defaultProps.date;
this.displayOtherMonthDays = CalendarComponent.defaultProps.displayOtherMonthDays;
this.prefix = config.components.prefix;
this.selectYearAnimationDuration = 150;
this.scrollToActiveYear = this.scrollToActiveYear.bind(this);
this.onSelectDayEmitter = new EventEmitter();
this.dayLabels = this.getDayLabels(days);
this.monthLabels = this.getMonthLabels(months);
}
/**
* @return {?}
*/
ngOnInit() {
this.init();
}
/**
* @return {?}
*/
ngOnChanges() {
this.init();
}
/**
* @return {?}
*/
init() {
/** @type {?} */
const dateExists = (typeof this.date !== 'undefined' && this.date !== null);
/** @type {?} */
const openDate = dateExists ? this.date : new Date();
/** @type {?} */
const isToday = this.isTodayDate(openDate);
/** @type {?} */
const month = openDate.getMonth();
/** @type {?} */
const year = openDate.getFullYear();
this.weeks = this.fillWeeks(month, year);
this.years = this.fillYears(year);
this.selectedDate = this.createDateModel(openDate, false, isToday, dateExists);
}
/**
* @param {?} dayLabels
* @return {?}
*/
getDayLabels(dayLabels) {
return [
dayLabels.sunday,
dayLabels.monday,
dayLabels.tuesday,
dayLabels.wednesday,
dayLabels.thursday,
dayLabels.friday,
dayLabels.saturday
];
}
/**
* @param {?} monthLabels
* @return {?}
*/
getMonthLabels(monthLabels) {
return [
monthLabels.january,
monthLabels.february,
monthLabels.march,
monthLabels.april,
monthLabels.may,
monthLabels.june,
monthLabels.july,
monthLabels.august,
monthLabels.september,
monthLabels.october,
monthLabels.november,
monthLabels.december
];
}
/**
* @param {?} date
* @param {?} isOutOfMonth
* @param {?} isToday
* @param {?} showSelected
* @return {?}
*/
createDateModel(date, isOutOfMonth, isToday, showSelected) {
/** @type {?} */
const weekDay = date.getDay();
/** @type {?} */
const month = date.getMonth();
/** @type {?} */
const dateModel = {
ISODate: this.generateISODate(date),
date: date,
dayLabel: this.dayLabels[weekDay],
isOutOfMonth: isOutOfMonth,
isToday: isToday,
monthLabel: this.monthLabels[month],
showSelected: showSelected
};
return dateModel;
}
/**
* @param {?} day
* @param {?} month
* @param {?} year
* @return {?}
*/
createDateObject(day, month, year) {
/** @type {?} */
const date = new Date();
date.setDate(day);
date.setMonth(month);
date.setFullYear(year);
return date;
}
/**
* @param {?} currentYear
* @return {?}
*/
fillYears(currentYear) {
/** @type {?} */
const firstYear = currentYear - 100;
/** @type {?} */
const lastYear = currentYear + 100;
/** @type {?} */
const years = [];
for (let i = firstYear; i <= lastYear; i++) {
years.push(i);
}
return years;
}
/**
* @param {?} month
* @param {?} year
* @return {?}
*/
fillWeeks(month, year) {
this.selectedMonth = {
label: this.monthLabels[month],
number: month,
year: year
};
/** @type {?} */
const finalMonthDay = this.createDateObject(0, month, year);
/** @type {?} */
const weeks = [];
/** @type {?} */
let initMonthDate = new Date(year, month, 1);
/** @type {?} */
let day = 0 - initMonthDate.getDay();
/** @type {?} */
let daysInWeek = [];
while (initMonthDate.getDay() !== 0 || finalMonthDay >= initMonthDate) {
++day;
initMonthDate = new Date(year, month, day);
daysInWeek.push(this.createDayDate(initMonthDate, day, finalMonthDay));
if (daysInWeek.length === 7) {
weeks.push(daysInWeek);
daysInWeek = [];
}
}
return weeks;
}
/**
* @param {?} date
* @return {?}
*/
isTodayDate(date) {
/** @type {?} */
const ISOCurrentDate = this.generateISODate(new Date());
/** @type {?} */
const ISODate = this.generateISODate(date);
/** @type {?} */
const isToday = (ISODate === ISOCurrentDate);
return isToday;
}
/**
* @param {?} date
* @param {?} dayNumber
* @param {?} finalMonthDay
* @return {?}
*/
createDayDate(date, dayNumber, finalMonthDay) {
/** @type {?} */
const isToday = this.isTodayDate(date);
/** @type {?} */
const isOutOfMonth = (dayNumber <= 0 || date > finalMonthDay);
return this.createDateModel(date, isOutOfMonth, isToday, true);
}
/**
* @return {?}
*/
showPrevMonth() {
/** @type {?} */
const month = this.selectedMonth.number;
/** @type {?} */
const year = this.selectedMonth.year;
/** @type {?} */
const prevMonth = month >= 1
? month - 1
: 11;
/** @type {?} */
const prevYear = month < 1
? year - 1
: year;
this.weeks = this.fillWeeks(prevMonth, prevYear);
}
/**
* @return {?}
*/
showNextMonth() {
/** @type {?} */
const month = this.selectedMonth.number;
/** @type {?} */
const year = this.selectedMonth.year;
/** @type {?} */
const nextMonth = month < 11
? month + 1
: 0;
/** @type {?} */
const nextYear = month >= 11
? year + 1
: year;
this.weeks = this.fillWeeks(nextMonth, nextYear);
}
/**
* @param {?} date
* @return {?}
*/
generateISODate(date) {
/** @type {?} */
const day = date.getDate();
/** @type {?} */
const month = date.getMonth() + 1;
/** @type {?} */
const year = date.getFullYear();
/** @type {?} */
const dayString = day > 9
? day
: `0${day}`;
/** @type {?} */
const monthString = month > 9
? month
: `0${month}`;
return `${year}-${monthString}-${dayString}`;
}
/**
* @param {?} date
* @return {?}
*/
onSelectDay(date) {
if (date.isOutOfMonth) {
return;
}
this.selectedDate = date;
this.onSelectDayEmitter.emit(this.selectedDate);
}
/**
* @param {?} year
* @return {?}
*/
onSelectYear(year) {
setTimeout((/**
* @return {?}
*/
() => {
/** @type {?} */
const day = this.selectedDate.date.getDate();
/** @type {?} */
const month = this.selectedDate.date.getMonth();
this.date = this.createDateObject(day, month, year);
this.showYears = false;
this.selectedDate = this.createDateModel(this.date, false, true, true);
this.weeks = this.fillWeeks(month, year);
}), this.selectYearAnimationDuration);
}
/**
* @return {?}
*/
displayYears() {
this.showYears = true;
setTimeout(this.scrollToActiveYear, 0);
}
/**
* @return {?}
*/
scrollToActiveYear() {
const { nativeElement } = this.yearsContainerRef;
/** @type {?} */
const activeYear = nativeElement.querySelector('.selected');
if (activeYear) {
/** @type {?} */
const top = this.getScrollCenter(nativeElement, activeYear);
nativeElement.scrollTop = top;
}
}
/**
* @param {?} container
* @param {?} internalElement
* @return {?}
*/
getScrollCenter(container, internalElement) {
/** @type {?} */
const yearTop = internalElement.offsetTop;
/** @type {?} */
const yearMiddleHeight = internalElement.offsetHeight / 2;
/** @type {?} */
const containerTop = container.offsetTop;
/** @type {?} */
const containerMiddleHeight = container.offsetHeight / 2;
/** @type {?} */
const elementRelativeTop = (yearTop - containerTop) - (containerMiddleHeight - yearMiddleHeight);
if (elementRelativeTop < 0) {
return 0;
}
return elementRelativeTop;
}
}
CalendarComponent.defaultProps = {
className: '',
date: new Date(),
displayOtherMonthDays: true
};
CalendarComponent.decorators = [
{ type: Component, args: [{
selector: `${config.components.prefix}-calendar }`,
template: "<div [ngClass]=\"[prefix + '-calendar', className]\">\n <div [ngClass]=\"prefix + '-calendar-header'\">\n <div [ngClass]=\"prefix + '-calendar-year'\">\n <materialize-button (onClick)=\"displayYears()\">{{ selectedMonth.year }}</materialize-button>\n </div>\n <div [ngClass]=\"prefix + '-calendar-date'\">\n <materialize-button (onClick)=\"showYears = false\">\n {{ selectedDate.dayLabel.shortName }}, {{ selectedDate.monthLabel.shortName }} {{ selectedDate.date.getDate() }}\n </materialize-button>\n </div>\n </div>\n\n <div [ngClass]=\"prefix + '-calendar-body'\">\n <ng-container *ngIf=\"!showYears\">\n <div [ngClass]=\"prefix + '-calendar-controls'\">\n <div [ngClass]=\"prefix + '-calendar-control'\" materializeRipple (click)=\"showPrevMonth()\">\n <materialize-icon>chevron_left</materialize-icon>\n </div>\n <div [ngClass]=\"prefix + '-calendar-month'\">\n {{ selectedMonth.label.shortName }} {{ selectedMonth.year }}\n </div>\n <div [ngClass]=\"prefix + '-calendar-control'\" materializeRipple (click)=\"showNextMonth()\">\n <materialize-icon>chevron_right</materialize-icon>\n </div>\n </div>\n \n <table [ngClass]=\"prefix + '-calendar-table'\">\n <thead>\n <tr>\n <td [ngClass]=\"prefix + '-calendar-day-name'\" *ngFor=\"let day of dayLabels\">{{ day.shortestName }}</td>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let week of weeks\">\n <td *ngFor=\"let day of week\">\n <div [ngClass]=\"prefix + '-calendar-day'\"\n (click)=\"onSelectDay(day)\"\n *ngIf=\"!day.isOutOfMonth || displayOtherMonthDays\"\n \n [class.current]=\"day.isToday\"\n [class.selected]=\"selectedDate.showSelected && selectedDate.ISODate === day.ISODate\"\n [class.disabled]=\"day.isOutOfMonth\"\n \n materializeRipple\n [rippleDuration]=\"800\"\n >\n {{ day.date.getDate() }}\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </ng-container>\n \n <div [ngClass]=\"prefix + '-calendar-years'\" #yearsContainer>\n <ng-container *ngIf=\"showYears\">\n <div [ngClass]=\"prefix + '-calendar-year-option'\"\n *ngFor=\"let year of years\"\n\n (click)=\"onSelectYear(year)\"\n [class.selected]=\"year === selectedMonth.year\"\n\n materializeRipple\n [rippleDuration]=\"selectYearAnimationDuration\"\n >\n {{ year }}\n </div>\n </ng-container>\n </div>\n </div>\n</div>\n"
}] }
];
/** @nocollapse */
CalendarComponent.ctorParameters = () => [];
CalendarComponent.propDecorators = {
yearsContainerRef: [{ type: ViewChild, args: ['yearsContainer', { static: false },] }],
onSelectDayEmitter: [{ type: Output, args: ['onSelectDay',] }],
className: [{ type: Input }],
date: [{ type: Input }],
displayOtherMonthDays: [{ type: Input }]
};
if (false) {
/** @type {?} */
CalendarComponent.defaultProps;
/** @type {?} */
CalendarComponent.prototype.yearsContainerRef;
/** @type {?} */
CalendarComponent.prototype.onSelectDayEmitter;
/** @type {?} */
CalendarComponent.prototype.className;
/** @type {?} */
CalendarComponent.prototype.date;
/** @type {?} */
CalendarComponent.prototype.displayOtherMonthDays;
/** @type {?} */
CalendarComponent.prototype.prefix;
/** @type {?} */
CalendarComponent.prototype.dayLabels;
/** @type {?} */
CalendarComponent.prototype.monthLabels;
/** @type {?} */
CalendarComponent.prototype.selectedDate;
/** @type {?} */
CalendarComponent.prototype.selectedMonth;
/** @type {?} */
CalendarComponent.prototype.showYears;
/** @type {?} */
CalendarComponent.prototype.weeks;
/** @type {?} */
CalendarComponent.prototype.years;
/** @type {?} */
CalendarComponent.prototype.selectYearAnimationDuration;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbWF0ZXJpYWxpemUtYW5ndWxhci8iLCJzb3VyY2VzIjpbImFwcC9jb21wbGV0ZWQtY29tcG9uZW50cy9jYWxlbmRhci9jYWxlbmRhci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBU0EsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUN6RCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFNeEQsTUFBTSxPQUFPLGlCQUFpQjtJQTJCNUI7UUFoQlMsY0FBUyxHQUFXLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUM7UUFDN0QsU0FBSSxHQUFTLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUM7UUFDakQsMEJBQXFCLEdBQVksaUJBQWlCLENBQUMsWUFBWSxDQUFDLHFCQUFxQixDQUFDO1FBRXhGLFdBQU0sR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQztRQVVsQyxnQ0FBMkIsR0FBRyxHQUFHLENBQUM7UUFHdkMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFN0QsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksWUFBWSxFQUFhLENBQUM7UUFFeEQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMs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V29ya3lsYWIuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3dvcmt5bGFiL21hdGVyaWFsaXplLWFuZ3VsYXIvbWFzdGVyL0xJQ0VOU0VcbiAqL1xuXG5pbXBvcnQgeyBDYWxlbmRhck1vZGVsLCBEYXRlTGFiZWwsIERhdGVNb2RlbCwgRGF5TGFiZWxzLCBNb250aExhYmVscywgTW9udGhNb2RlbCB9IGZyb20gJy4vY2FsZW5kYXIubW9kZWwnO1xuaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkNoYW5nZXMsIE9uSW5pdCwgT3V0cHV0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGNvbmZpZyB9IGZyb20gJy4uLy4uL2NvbmZpZyc7XG5pbXBvcnQgeyBkYXlzIH0gZnJvbSAnLi4vLi4vZml4dHVyZXMvY2FsZW5kYXItd2Vlay1kYXlzJztcbmltcG9ydCB7IG1vbnRocyB9IGZyb20gJy4uLy4uL2ZpeHR1cmVzL2NhbGVuZGFyLW1vbnRocyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogYCR7IGNvbmZpZy5jb21wb25lbnRzLnByZWZpeCB9LWNhbGVuZGFyIH1gLFxuICB0ZW1wbGF0ZVVybDogJy4vY2FsZW5kYXIuY29tcG9uZW50Lmh0bWwnXG59KVxuZXhwb3J0IGNsYXNzIENhbGVuZGFyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xuICBzdGF0aWMgcmVhZG9ubHkgZGVmYXVsdFByb3BzOiBDYWxlbmRhck1vZGVsID0ge1xuICAgIGNsYXNzTmFtZTogJycsXG4gICAgZGF0ZTogbmV3IERhdGUoKSxcbiAgICBkaXNwbGF5T3RoZXJNb250aERheXM6IHRydWVcbiAgfTtcblxuICBAVmlld0NoaWxkKCd5ZWFyc0NvbnRhaW5lcicsIHsgc3RhdGljOiBmYWxzZSB9KSB5ZWFyc0NvbnRhaW5lclJlZjogRWxlbWVudFJlZjtcblxuICBAT3V0cHV0KCdvblNlbGVjdERheScpIG9uU2VsZWN0RGF5RW1pdHRlcjogRXZlbnRFbWl0dGVyPERhdGVNb2RlbD47XG5cbiAgQElucHV0KCkgY2xhc3NOYW1lOiBzdHJpbmcgPSBDYWxlbmRhckNvbXBvbmVudC5kZWZhdWx0UHJvcHMuY2xhc3NOYW1lO1xuICBASW5wdXQoKSBkYXRlOiBEYXRlID0gQ2FsZW5kYXJDb21wb25lbnQuZGVmYXVsdFByb3BzLmRhdGU7XG4gIEBJbnB1dCgpIGRpc3BsYXlPdGhlck1vbnRoRGF5czogYm9vbGVhbiA9IENhbGVuZGFyQ29tcG9uZW50LmRlZmF1bHRQcm9wcy5kaXNwbGF5T3RoZXJNb250aERheXM7XG5cbiAgcHVibGljIHByZWZpeCA9IGNvbmZpZy5jb21wb25lbnRzLnByZWZpeDtcblxuICBwdWJsaWMgZGF5TGFiZWxzOiBBcnJheTxEYXRlTGFiZWw+O1xuICBwdWJsaWMgbW9udGhMYWJlbHM6IEFycmF5PERhdGVMYWJlbD47XG4gIHB1YmxpYyBzZWxlY3RlZERhdGU6IERhdGVNb2RlbDtcbiAgcHVibGljIHNlbGVjdGVkTW9udGg6IE1vbnRoTW9kZWw7XG4gIHB1YmxpYyBzaG93WWVhcnM6IGJvb2xlYW47XG4gIHB1YmxpYyB3ZWVrczogQXJyYXk8QXJyYXk8RGF0ZU1vZGVsPj47XG4gIHB1YmxpYyB5ZWFyczogQXJyYXk8bnVtYmVyPjtcblxuICBwdWJsaWMgc2VsZWN0WWVhckFuaW1hdGlvbkR1cmF0aW9uID0gMTUwO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuc2Nyb2xsVG9BY3RpdmVZZWFyID0gdGhpcy5zY3JvbGxUb0FjdGl2ZVllYXIuYmluZCh0aGlzKTtcblxuICAgIHRoaXMub25TZWxlY3REYXlFbWl0dGVyID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlTW9kZWw+KCk7XG5cbiAgICB0aGlzLmRheUxhYmVscyA9IHRoaXMuZ2V0RGF5TGFiZWxzKGRheXMpO1xuICAgIHRoaXMubW9udGhMYWJlbHMgPSB0aGlzLmdldE1vbnRoTGFiZWxzKG1vbnRocyk7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmluaXQoKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKCkge1xuICAgIHRoaXMuaW5pdCgpO1xuICB9XG5cbiAgaW5pdCgpIHtcbiAgICBjb25zdCBkYXRlRXhpc3RzID0gKHR5cGVvZiB0aGlzLmRhdGUgIT09ICd1bmRlZmluZWQnICYmIHRoaXMuZGF0ZSAhPT0gbnVsbCk7XG4gICAgY29uc3Qgb3BlbkRhdGUgPSBkYXRlRXhpc3RzID8gdGhpcy5kYXRlIDogbmV3IERhdGUoKTtcbiAgICBjb25zdCBpc1RvZGF5ID0gdGhpcy5pc1RvZGF5RGF0ZShvcGVuRGF0ZSk7XG4gICAgY29uc3QgbW9udGggPSBvcGVuRGF0ZS5nZXRNb250aCgpO1xuICAgIGNvbnN0IHllYXIgPSBvcGVuRGF0ZS5nZXRGdWxsWWVhcigpO1xuXG4gICAgdGhpcy53ZWVrcyA9IHRoaXMuZmlsbFdlZWtzKG1vbnRoLCB5ZWFyKTtcbiAgICB0aGlzLnllYXJzID0gdGhpcy5maWxsWWVhcnMoeWVhcik7XG5cbiAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IHRoaXMuY3JlYXRlRGF0ZU1vZGVsKG9wZW5EYXRlLCBmYWxzZSwgaXNUb2RheSwgZGF0ZUV4aXN0cyk7XG4gIH1cblxuICBnZXREYXlMYWJlbHMoZGF5TGFiZWxzOiBEYXlMYWJlbHMpOiBBcnJheTxEYXRlTGFiZWw+IHtcbiAgICByZXR1cm4gW1xuICAgICAgZGF5TGFiZWxzLnN1bmRheSxcbiAgICAgIGRheUxhYmVscy5tb25kYXksXG4gICAgICBkYXlMYWJlbHMudHVlc2RheSxcbiAgICAgIGRheUxhYmVscy53ZWRuZXNkYXksXG4gICAgICBkYXlMYWJlbHMudGh1cnNkYXksXG4gICAgICBkYXlMYWJlbHMuZnJpZGF5LFxuICAgICAgZGF5TGFiZWxzLnNhdHVyZGF5XG4gICAgXTtcbiAgfVxuXG4gIGdldE1vbnRoTGFiZWxzKG1vbnRoTGFiZWxzOiBNb250aExhYmVscyk6IEFycmF5PERhdGVMYWJlbD4ge1xuICAgIHJldHVybiBbXG4gICAgICBtb250aExhYmVscy5qYW51YXJ5LFxuICAgICAgbW9udGhMYWJlbHMuZmVicnVhcnksXG4gICAgICBtb250aExhYmVscy5tYXJjaCxcbiAgICAgIG1vbnRoTGFiZWxzLmFwcmlsLFxuICAgICAgbW9udGhMYWJlbHMubWF5LFxuICAgICAgbW9udGhMYWJlbHMuanVuZSxcbiAgICAgIG1vbnRoTGFiZWxzLmp1bHksXG4gICAgICBtb250aExhYmVscy5hdWd1c3QsXG4gICAgICBtb250aExhYmVscy5zZXB0ZW1iZXIsXG4gICAgICBtb250aExhYmVscy5vY3RvYmVyLFxuICAgICAgbW9udGhMYWJlbHMubm92ZW1iZXIsXG4gICAgICBtb250aExhYmVscy5kZWNlbWJlclxuICAgIF07XG4gIH1cblxuICBjcmVhdGVEYXRlTW9kZWwoZGF0ZTogRGF0ZSwgaXNPdXRPZk1vbnRoOiBib29sZWFuLCBpc1RvZGF5OiBib29sZWFuLCBzaG93U2VsZWN0ZWQ6IGJvb2xlYW4pOiBEYXRlTW9kZWwge1xuICAgIGNvbnN0IHdlZWtEYXkgPSBkYXRlLmdldERheSgpO1xuICAgIGNvbnN0IG1vbnRoID0gZGF0ZS5nZXRNb250aCgpO1xuXG4gICAgY29uc3QgZGF0ZU1vZGVsOiBEYXRlTW9kZWwgPSB7XG4gICAgICBJU09EYXRlOiB0aGlzLmdlbmVyYXRlSVNPRGF0ZShkYXRlKSxcbiAgICAgIGRhdGU6IGRhdGUsXG4gICAgICBkYXlMYWJlbDogdGhpcy5kYXlMYWJlbHNbd2Vla0RheV0sXG4gICAgICBpc091dE9mTW9udGg6IGlzT3V0T2ZNb250aCxcbiAgICAgIGlzVG9kYXk6IGlzVG9kYXksXG4gICAgICBtb250aExhYmVsOiB0aGlzLm1vbnRoTGFiZWxzW21vbnRoXSxcbiAgICAgIHNob3dTZWxlY3RlZDogc2hvd1NlbGVjdGVkXG4gICAgfTtcblxuICAgIHJldHVybiBkYXRlTW9kZWw7XG4gIH1cblxuICBjcmVhdGVEYXRlT2JqZWN0KGRheTogbnVtYmVyLCBtb250aDogbnVtYmVyLCB5ZWFyOiBudW1iZXIpOiBEYXRlIHtcbiAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKTtcblxuICAgIGRhdGUuc2V0RGF0ZShkYXkpO1xuICAgIGRhdGUuc2V0TW9udGgobW9udGgpO1xuICAgIGRhdGUuc2V0RnVsbFllYXIoeWVhcik7XG5cbiAgICByZXR1cm4gZGF0ZTtcbiAgfVxuXG4gIGZpbGxZZWFycyhjdXJyZW50WWVhcjogbnVtYmVyKTogQXJyYXk8bnVtYmVyPiB7XG4gICAgY29uc3QgZmlyc3RZZWFyID0gY3VycmVudFllYXIgLSAxMDA7XG4gICAgY29uc3QgbGFzdFllYXIgPSBjdXJyZW50WWVhciArIDEwMDtcbiAgICBjb25zdCB5ZWFycyA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IGZpcnN0WWVhcjsgaSA8PSBsYXN0WWVhcjsgaSsrKSB7XG4gICAgICB5ZWFycy5wdXNoKGkpO1xuICAgIH1cblxuICAgIHJldHVybiB5ZWFycztcbiAgfVxuXG4gIGZpbGxXZWVrcyhtb250aDogbnVtYmVyLCB5ZWFyOiBudW1iZXIpIHtcbiAgICB0aGlzLnNlbGVjdGVkTW9udGggPSB7XG4gICAgICBsYWJlbDogdGhpcy5tb250aExhYmVsc1ttb250aF0sXG4gICAgICBudW1iZXI6IG1vbnRoLFxuICAgICAgeWVhcjogeWVhclxuICAgIH07XG5cbiAgICBjb25zdCBmaW5hbE1vbnRoRGF5ID0gdGhpcy5jcmVhdGVEYXRlT2JqZWN0KDAsIG1vbnRoLCB5ZWFyKTtcbiAgICBjb25zdCB3ZWVrcyA9IFtdO1xuXG4gICAgbGV0IGluaXRNb250aERhdGUgPSBuZXcgRGF0ZSh5ZWFyLCBtb250aCwgMSk7XG4gICAgbGV0IGRheSA9IDAgLSBpbml0TW9udGhEYXRlLmdldERheSgpO1xuICAgIGxldCBkYXlzSW5XZWVrID0gW107XG5cbiAgICB3aGlsZSAoaW5pdE1vbnRoRGF0ZS5nZXREYXkoKSAhPT0gMCB8fCBmaW5hbE1vbnRoRGF5ID49IGluaXRNb250aERhdGUpIHtcbiAgICAgICsrZGF5O1xuXG4gICAgICBpbml0TW9udGhEYXRlID0gbmV3IERhdGUoeWVhciwgbW9udGgsIGRheSk7XG5cbiAgICAgIGRheXNJbldlZWsucHVzaCh0aGlzLmNyZWF0ZURheURhdGUoaW5pdE1vbnRoRGF0ZSwgZGF5LCBmaW5hbE1vbnRoRGF5KSk7XG5cbiAgICAgIGlmIChkYXlzSW5XZWVrLmxlbmd0aCA9PT0gNykge1xuICAgICAgICB3ZWVrcy5wdXNoKGRheXNJbldlZWspO1xuICAgICAgICBkYXlzSW5XZWVrID0gW107XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHdlZWtzO1xuICB9XG5cbiAgaXNUb2RheURhdGUoZGF0ZTogRGF0ZSkge1xuICAgIGNvbnN0IElTT0N1cnJlbnREYXRlID0gdGhpcy5nZW5lcmF0ZUlTT0RhdGUobmV3IERhdGUoKSk7XG4gICAgY29uc3QgSVNPRGF0ZSA9IHRoaXMuZ2VuZXJhdGVJU09EYXRlKGRhdGUpO1xuICAgIGNvbnN0IGlzVG9kYXkgPSAoSVNPRGF0ZSA9PT0gSVNPQ3VycmVudERhdGUpO1xuXG4gICAgcmV0dXJuIGlzVG9kYXk7XG4gIH1cblxuICBjcmVhdGVEYXlEYXRlKGRhdGU6IERhdGUsIGRheU51bWJlcjogbnVtYmVyLCBmaW5hbE1vbnRoRGF5OiBEYXRlKTogRGF0ZU1vZGVsIHtcbiAgICBjb25zdCBpc1RvZGF5ID0gdGhpcy5pc1RvZGF5RGF0ZShkYXRlKTtcbiAgICBjb25zdCBpc091dE9mTW9udGggPSAoZGF5TnVtYmVyIDw9IDAgfHwgZGF0ZSA+IGZpbmFsTW9udGhEYXkpO1xuXG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlRGF0ZU1vZGVsKGRhdGUsIGlzT3V0T2ZNb250aCwgaXNUb2RheSwgdHJ1ZSk7XG4gIH1cblxuICBzaG93UHJldk1vbnRoKCkge1xuICAgIGNvbnN0IG1vbnRoID0gdGhpcy5zZWxlY3RlZE1vbnRoLm51bWJlcjtcbiAgICBjb25zdCB5ZWFyID0gdGhpcy5zZWxlY3RlZE1vbnRoLnllYXI7XG5cbiAgICBjb25zdCBwcmV2TW9udGggPSBtb250aCA+PSAxXG4gICAgICA/IG1vbnRoIC0gMVxuICAgICAgOiAxMTtcblxuICAgIGNvbnN0IHByZXZZZWFyID0gbW9udGggPCAxXG4gICAgICA/IHllYXIgLSAxXG4gICAgICA6IHllYXI7XG5cbiAgICB0aGlzLndlZWtzID0gdGhpcy5maWxsV2Vla3MocHJldk1vbnRoLCBwcmV2WWVhcik7XG4gIH1cblxuICBzaG93TmV4dE1vbnRoKCkge1xuICAgIGNvbnN0IG1vbnRoID0gdGhpcy5zZWxlY3RlZE1vbnRoLm51bWJlcjtcbiAgICBjb25zdCB5ZWFyID0gdGhpcy5zZWxlY3RlZE1vbnRoLnllYXI7XG5cbiAgICBjb25zdCBuZXh0TW9udGggPSBtb250aCA8IDExXG4gICAgICA/IG1vbnRoICsgMVxuICAgICAgOiAwO1xuXG4gICAgY29uc3QgbmV4dFllYXIgPSBtb250aCA+PSAxMVxuICAgICAgPyB5ZWFyICsgMVxuICAgICAgOiB5ZWFyO1xuXG4gICAgdGhpcy53ZWVrcyA9IHRoaXMuZmlsbFdlZWtzKG5leHRNb250aCwgbmV4dFllYXIpO1xuICB9XG5cbiAgZ2VuZXJhdGVJU09EYXRlKGRhdGU6IERhdGUpIHtcbiAgICBjb25zdCBkYXkgPSBkYXRlLmdldERhdGUoKTtcbiAgICBjb25zdCBtb250aCA9IGRhdGUuZ2V0TW9udGgoKSArIDE7XG4gICAgY29uc3QgeWVhciA9IGRhdGUuZ2V0RnVsbFllYXIoKTtcblxuICAgIGNvbnN0IGRheVN0cmluZyA9IGRheSA+IDlcbiAgICAgID8gZGF5XG4gICAgICA6IGAwJHsgZGF5IH1gO1xuXG4gICAgY29uc3QgbW9udGhTdHJpbmcgPSBtb250aCA+IDlcbiAgICAgID8gbW9udGhcbiAgICAgIDogYDAkeyBtb250aCB9YDtcblxuICAgIHJldHVybiBgJHsgeWVhciB9LSR7IG1vbnRoU3RyaW5nIH0tJHsgZGF5U3RyaW5nIH1gO1xuICB9XG5cbiAgb25TZWxlY3REYXkoZGF0ZTogRGF0ZU1vZGVsKSB7XG4gICAgaWYgKGRhdGUuaXNPdXRPZk1vbnRoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zZWxlY3RlZERhdGUgPSBkYXRlO1xuICAgIHRoaXMub25TZWxlY3REYXlFbWl0dGVyLmVtaXQodGhpcy5zZWxlY3RlZERhdGUpO1xuICB9XG5cbiAgb25TZWxlY3RZZWFyKHllYXI6IG51bWJlcikge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgY29uc3QgZGF5ID0gdGhpcy5zZWxlY3RlZERhdGUuZGF0ZS5nZXREYXRlKCk7XG4gICAgICBjb25zdCBtb250aCA9IHRoaXMuc2VsZWN0ZWREYXRlLmRhdGUuZ2V0TW9udGgoKTtcblxuICAgICAgdGhpcy5kYXRlID0gdGhpcy5jcmVhdGVEYXRlT2JqZWN0KGRheSwgbW9udGgsIHllYXIpO1xuICAgICAgdGhpcy5zaG93WWVhcnMgPSBmYWxzZTtcbiAgICAgIHRoaXMuc2VsZWN0ZWREYXRlID0gdGhpcy5jcmVhdGVEYXRlTW9kZWwodGhpcy5kYXRlLCBmYWxzZSwgdHJ1ZSwgdHJ1ZSk7XG5cbiAgICAgIHRoaXMud2Vla3MgPSB0aGlzLmZpbGxXZWVrcyhtb250aCwgeWVhcik7XG4gICAgfSwgdGhpcy5zZWxlY3RZZWFyQW5pbWF0aW9uRHVyYXRpb24pO1xuICB9XG5cbiAgZGlzcGxheVllYXJzKCkge1xuICAgIHRoaXMuc2hvd1llYXJzID0gdHJ1ZTtcblxuICAgIHNldFRpbWVvdXQodGhpcy5zY3JvbGxUb0FjdGl2ZVllYXIsIDApO1xuICB9XG5cbiAgc2Nyb2xsVG9BY3RpdmVZZWFyKCkge1xuICAgIGNvbnN0IHsgbmF0aXZlRWxlbWVudCB9ID0gdGhpcy55ZWFyc0NvbnRhaW5lclJlZjtcbiAgICBjb25zdCBhY3RpdmVZZWFyOiBIVE1MRWxlbWVudCA9IG5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignLnNlbGVjdGVkJyk7XG5cbiAgICBpZiAoYWN0aXZlWWVhcikge1xuICAgICAgY29uc3QgdG9wID0gdGhpcy5nZXRTY3JvbGxDZW50ZXIobmF0aXZlRWxlbWVudCwgYWN0aXZlWWVhcik7XG5cbiAgICAgIG5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wID0gdG9wO1xuICAgIH1cbiAgfVxuXG4gIGdldFNjcm9sbENlbnRlcihjb250YWluZXI6IEhUTUxFbGVtZW50LCBpbnRlcm5hbEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogbnVtYmVyIHtcbiAgICBjb25zdCB5ZWFyVG9wID0gaW50ZXJuYWxFbGVtZW50Lm9mZnNldFRvcDtcbiAgICBjb25zdCB5ZWFyTWlkZGxlSGVpZ2h0ID0gaW50ZXJuYWxFbGVtZW50Lm9mZnNldEhlaWdodCAvIDI7XG5cbiAgICBjb25zdCBjb250YWluZXJUb3AgPSBjb250YWluZXIub2Zmc2V0VG9wO1xuICAgIGNvbnN0IGNvbnRhaW5lck1pZGRsZUhlaWdodCA9IGNvbnRhaW5lci5vZmZzZXRIZWlnaHQgLyAyO1xuXG4gICAgY29uc3QgZWxlbWVudFJlbGF0aXZlVG9wID0gKHllYXJUb3AgLSBjb250YWluZXJUb3ApIC0gKGNvbnRhaW5lck1pZGRsZUhlaWdodCAtIHllYXJNaWRkbGVIZWlnaHQpO1xuXG4gICAgaWYgKGVsZW1lbnRSZWxhdGl2ZVRvcCA8IDApIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIHJldHVybiBlbGVtZW50UmVsYXRpdmVUb3A7XG4gIH1cbn1cbiJdfQ==