@angular-mdl/core
Version:
Angular components, directives and styles based on material design lite https://getmdl.io.
268 lines • 34.5 kB
JavaScript
import { Component, Injectable, Input, Renderer2, ViewChild, ViewEncapsulation, } from "@angular/core";
import { MdlError } from "../common/mdl-error";
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
const BOTTOM_LEFT = "bottom-left";
const BOTTOM_RIGHT = "bottom-right";
const TOP_LEFT = "top-left";
const TOP_RIGHT = "top-right";
const UNALIGNED = "unaligned";
// Total duration of the menu animation.
const TRANSITION_DURATION_SECONDS = 0.3;
// The fraction of the total duration we want to use for menu item animations.
const TRANSITION_DURATION_FRACTION = 0.8;
// How long the menu stays open after choosing an option (so the user can see
// the ripple).
const CLOSE_TIMEOUT = 175;
const CSS_ALIGN_MAP = {};
CSS_ALIGN_MAP[BOTTOM_LEFT] = "mdl-menu--bottom-left";
CSS_ALIGN_MAP[BOTTOM_RIGHT] = "mdl-menu--bottom-right";
CSS_ALIGN_MAP[TOP_LEFT] = "mdl-menu--top-left";
CSS_ALIGN_MAP[TOP_RIGHT] = "mdl-menu--top-right";
CSS_ALIGN_MAP[UNALIGNED] = "mdl-menu--unaligned";
export class MdlMenuError extends MdlError {
}
export class MdlMenuRegisty {
constructor() {
this.menuComponents = [];
}
add(menuComponent) {
this.menuComponents.push(menuComponent);
}
remove(menuComponent) {
const fromIndex = this.menuComponents.indexOf(menuComponent);
this.menuComponents.splice(fromIndex, 1);
}
hideAllExcept(menuComponent) {
this.menuComponents.forEach((component) => {
if (component !== menuComponent) {
component.hide();
}
});
}
}
MdlMenuRegisty.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MdlMenuRegisty, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
MdlMenuRegisty.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MdlMenuRegisty, providedIn: "root" });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MdlMenuRegisty, decorators: [{
type: Injectable,
args: [{
providedIn: "root",
}]
}] });
export class MdlMenuComponent {
constructor(renderer, menuRegistry) {
this.renderer = renderer;
this.menuRegistry = menuRegistry;
this.cssPosition = "mdl-menu--bottom-left";
this.isVisible = false;
this.menuRegistry.add(this);
}
ngOnInit() {
this.cssPosition = CSS_ALIGN_MAP[this.position ?? BOTTOM_LEFT];
}
ngAfterViewInit() {
this.container = this.containerChild?.nativeElement;
this.menuElement = this.menuElementChild?.nativeElement;
this.outline = this.outlineChild?.nativeElement;
// Add a click listener to the document, to close the menu.
const callback = () => {
if (this.isVisible) {
this.hide();
}
return true;
};
this.renderer.listen("window", "click", callback);
this.renderer.listen("window", "touchstart", callback);
}
toggle(event, mdlButton) {
if (!mdlButton) {
throw new MdlMenuError(`MdlButtonComponent is required`);
}
if (this.isVisible) {
this.hide();
}
else {
this.show(event, mdlButton);
}
}
hideOnItemClicked() {
// Wait some time before closing menu, so the user can see the ripple.
setTimeout(() => {
this.hide();
}, CLOSE_TIMEOUT);
}
hide() {
// Remove all transition delays; menu items fade out concurrently.
document.querySelectorAll("mdl-menu-item").forEach((el) => {
el.style.removeProperty("transition-delay");
});
// this.menuItemComponents.toArray().forEach(mi => {
// mi.element.style.removeProperty('transition-delay');
// });
// Measure the inner element.
const rect = this.menuElement?.getBoundingClientRect();
const height = rect?.height;
const width = rect?.width;
// Turn on animation, and apply the final clip. Also make invisible.
// This triggers the transitions.
this.renderer.addClass(this.menuElement, "is-animating");
this.applyClip(height, width);
this.renderer.removeClass(this.container, "is-visible");
// Clean up after the animation is complete.
this.addAnimationEndListener();
this.isVisible = false;
}
show(event, mdlButton) {
this.menuRegistry.hideAllExcept(this);
event.stopPropagation();
const forElement = mdlButton.element;
const rect = forElement.getBoundingClientRect();
const forRect = forElement?.parentElement?.getBoundingClientRect();
if (!this.container || !forRect) {
return;
}
if (this.position === UNALIGNED) {
// Do not position the menu automatically. Requires the developer to
// manually specify position.
}
else if (this.position === BOTTOM_RIGHT) {
// Position below the "for" element, aligned to its right.
this.container.style.right = forRect.right - rect.right + "px";
this.container.style.top =
forElement.offsetTop + forElement.offsetHeight + "px";
}
else if (this.position === TOP_LEFT) {
// Position above the "for" element, aligned to its left.
this.container.style.left = forElement.offsetLeft + "px";
this.container.style.bottom = forRect.bottom - rect.top + "px";
}
else if (this.position === TOP_RIGHT) {
// Position above the "for" element, aligned to its right.
this.container.style.right = forRect.right - rect.right + "px";
this.container.style.bottom = forRect.bottom - rect.top + "px";
}
else {
// Default: position below the "for" element, aligned to its left.
this.container.style.left = forElement.offsetLeft + "px";
this.container.style.top =
forElement.offsetTop + forElement.offsetHeight + "px";
}
// Measure the inner element.
const height = this.menuElement?.getBoundingClientRect().height ?? 0;
const width = this.menuElement?.getBoundingClientRect().width ?? 0;
this.container.style.width = width + "px";
this.container.style.height = height + "px";
if (this.outline) {
this.outline.style.width = width + "px";
this.outline.style.height = height + "px";
}
const transitionDuration = TRANSITION_DURATION_SECONDS * TRANSITION_DURATION_FRACTION;
document.querySelectorAll("mdl-menu-item").forEach((el) => {
const mi = el;
let itemDelay;
if (this.position === TOP_LEFT || this.position === TOP_RIGHT) {
itemDelay =
((height - mi.offsetTop - mi.offsetHeight) / height) *
transitionDuration +
"s";
}
else {
itemDelay = (mi.offsetTop / height) * transitionDuration + "s";
}
mi.style.transitionDelay = itemDelay;
});
// Apply the initial clip to the text before we start animating.
this.applyClip(height, width);
this.renderer.addClass(this.container, "is-visible");
if (this.menuElement) {
this.menuElement.style.clip =
"rect(0 " + width + "px " + height + "px 0)";
this.renderer.addClass(this.menuElement, "is-animating");
}
this.addAnimationEndListener();
this.isVisible = true;
}
ngOnDestroy() {
this.menuRegistry.remove(this);
}
addAnimationEndListener() {
this.renderer.listen(this.menuElement, "transitionend", () => {
this.renderer.removeClass(this.menuElement, "is-animating");
return true;
});
}
applyClip(height, width) {
if (!this.menuElement) {
return;
}
if (this.position === UNALIGNED) {
// Do not clip.
this.menuElement.style.clip = "";
}
else if (this.position === BOTTOM_RIGHT) {
// Clip to the top right corner of the menu.
this.menuElement.style.clip =
"rect(0 " + width + "px " + "0 " + width + "px)";
}
else if (this.position === TOP_LEFT) {
// Clip to the bottom left corner of the menu.
this.menuElement.style.clip =
"rect(" + height + "px 0 " + height + "px 0)";
}
else if (this.position === TOP_RIGHT) {
// Clip to the bottom right corner of the menu.
this.menuElement.style.clip =
"rect(" +
height +
"px " +
width +
"px " +
height +
"px " +
width +
"px)";
}
else {
// Default: do not clip (same as clipping to the top left corner).
this.menuElement.style.clip = "";
}
}
}
MdlMenuComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MdlMenuComponent, deps: [{ token: i0.Renderer2 }, { token: MdlMenuRegisty }], target: i0.ɵɵFactoryTarget.Component });
MdlMenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MdlMenuComponent, selector: "mdl-menu", inputs: { position: ["mdl-menu-position", "position"] }, viewQueries: [{ propertyName: "containerChild", first: true, predicate: ["container"], descendants: true, static: true }, { propertyName: "menuElementChild", first: true, predicate: ["menuElement"], descendants: true, static: true }, { propertyName: "outlineChild", first: true, predicate: ["outline"], descendants: true, static: true }], exportAs: ["mdlMenu"], ngImport: i0, template: `
<div #container class="mdl-menu__container is-upgraded">
<div #outline class="mdl-menu__outline" [ngClass]="cssPosition"></div>
<div class="mdl-menu" #menuElement>
<ng-content></ng-content>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MdlMenuComponent, decorators: [{
type: Component,
args: [{
selector: "mdl-menu",
exportAs: "mdlMenu",
template: `
<div #container class="mdl-menu__container is-upgraded">
<div #outline class="mdl-menu__outline" [ngClass]="cssPosition"></div>
<div class="mdl-menu" #menuElement>
<ng-content></ng-content>
</div>
</div>
`,
encapsulation: ViewEncapsulation.None,
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: MdlMenuRegisty }]; }, propDecorators: { position: [{
type: Input,
args: ["mdl-menu-position"]
}], containerChild: [{
type: ViewChild,
args: ["container", { static: true }]
}], menuElementChild: [{
type: ViewChild,
args: ["menuElement", { static: true }]
}], outlineChild: [{
type: ViewChild,
args: ["outline", { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWRsLW1lbnUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29yZS9zcmMvbGliL21lbnUvbWRsLW1lbnUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxTQUFTLEVBRVQsVUFBVSxFQUNWLEtBQUssRUFHTCxTQUFTLEVBQ1QsU0FBUyxFQUNULGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0scUJBQXFCLENBQUM7OztBQUcvQyxNQUFNLFdBQVcsR0FBRyxhQUFhLENBQUM7QUFDbEMsTUFBTSxZQUFZLEdBQUcsY0FBYyxDQUFDO0FBQ3BDLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQztBQUM1QixNQUFNLFNBQVMsR0FBRyxXQUFXLENBQUM7QUFDOUIsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDO0FBRTlCLHdDQUF3QztBQUN4QyxNQUFNLDJCQUEyQixHQUFHLEdBQUcsQ0FBQztBQUN4Qyw4RUFBOEU7QUFDOUUsTUFBTSw0QkFBNEIsR0FBRyxHQUFHLENBQUM7QUFDekMsNkVBQTZFO0FBQzdFLGVBQWU7QUFDZixNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUM7QUFFMUIsTUFBTSxhQUFhLEdBQThCLEVBQUUsQ0FBQztBQUNwRCxhQUFhLENBQUMsV0FBVyxDQUFDLEdBQUcsdUJBQXVCLENBQUM7QUFDckQsYUFBYSxDQUFDLFlBQVksQ0FBQyxHQUFHLHdCQUF3QixDQUFDO0FBQ3ZELGFBQWEsQ0FBQyxRQUFRLENBQUMsR0FBRyxvQkFBb0IsQ0FBQztBQUMvQyxhQUFhLENBQUMsU0FBUyxDQUFDLEdBQUcscUJBQXFCLENBQUM7QUFDakQsYUFBYSxDQUFDLFNBQVMsQ0FBQyxHQUFHLHFCQUFxQixDQUFDO0FBRWpELE1BQU0sT0FBTyxZQUFhLFNBQVEsUUFBUTtDQUFHO0FBSzdDLE1BQU0sT0FB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QUM7b0JBQ1QsUUFBUSxFQUFFLFVBQVU7b0JBQ3BCLFFBQVEsRUFBRSxTQUFTO29CQUNuQixRQUFRLEVBQUU7Ozs7Ozs7R0FPVDtvQkFDRCxhQUFhLEVBQUUsaUJBQWlCLENBQUMsSUFBSTtpQkFDdEM7MEhBSUMsUUFBUTtzQkFEUCxLQUFLO3VCQUFDLG1CQUFtQjtnQkFJMUIsY0FBYztzQkFEYixTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBR3hDLGdCQUFnQjtzQkFEZixTQUFTO3VCQUFDLGFBQWEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRzFDLFlBQVk7c0JBRFgsU0FBUzt1QkFBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBJbmplY3RhYmxlLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIFJlbmRlcmVyMixcbiAgVmlld0NoaWxkLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IE1kbEVycm9yIH0gZnJvbSBcIi4uL2NvbW1vbi9tZGwtZXJyb3JcIjtcbmltcG9ydCB7IE1kbEJ1dHRvbkNvbXBvbmVudCB9IGZyb20gXCIuLi9idXR0b24vbWRsLWJ1dHRvbi5jb21wb25lbnRcIjtcblxuY29uc3QgQk9UVE9NX0xFRlQgPSBcImJvdHRvbS1sZWZ0XCI7XG5jb25zdCBCT1RUT01fUklHSFQgPSBcImJvdHRvbS1yaWdodFwiO1xuY29uc3QgVE9QX0xFRlQgPSBcInRvcC1sZWZ0XCI7XG5jb25zdCBUT1BfUklHSFQgPSBcInRvcC1yaWdodFwiO1xuY29uc3QgVU5BTElHTkVEID0gXCJ1bmFsaWduZWRcIjtcblxuLy8gVG90YWwgZHVyYXRpb24gb2YgdGhlIG1lbnUgYW5pbWF0aW9uLlxuY29uc3QgVFJBTlNJVElPTl9EVVJBVElPTl9TRUNPTkRTID0gMC4zO1xuLy8gVGhlIGZyYWN0aW9uIG9mIHRoZSB0b3RhbCBkdXJhdGlvbiB3ZSB3YW50IHRvIHVzZSBmb3IgbWVudSBpdGVtIGFuaW1hdGlvbnMuXG5jb25zdCBUUkFOU0lUSU9OX0RVUkFUSU9OX0ZSQUNUSU9OID0gMC44O1xuLy8gSG93IGxvbmcgdGhlIG1lbnUgc3RheXMgb3BlbiBhZnRlciBjaG9vc2luZyBhbiBvcHRpb24gKHNvIHRoZSB1c2VyIGNhbiBzZWVcbi8vIHRoZSByaXBwbGUpLlxuY29uc3QgQ0xPU0VfVElNRU9VVCA9IDE3NTtcblxuY29uc3QgQ1NTX0FMSUdOX01BUDogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuQ1NTX0FMSUdOX01BUFtCT1RUT01fTEVGVF0gPSBcIm1kbC1tZW51LS1ib3R0b20tbGVmdFwiO1xuQ1NTX0FMSUdOX01BUFtCT1RUT01fUklHSFRdID0gXCJtZGwtbWVudS0tYm90dG9tLXJpZ2h0XCI7XG5DU1NfQUxJR05fTUFQW1RPUF9MRUZUXSA9IFwibWRsLW1lbnUtLXRvcC1sZWZ0XCI7XG5DU1NfQUxJR05fTUFQW1RPUF9SSUdIVF0gPSBcIm1kbC1tZW51LS10b3AtcmlnaHRcIjtcbkNTU19BTElHTl9NQVBbVU5BTElHTkVEXSA9IFwibWRsLW1lbnUtLXVuYWxpZ25lZFwiO1xuXG5leHBvcnQgY2xhc3MgTWRsTWVudUVycm9yIGV4dGVuZHMgTWRsRXJyb3Ige31cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiBcInJvb3RcIixcbn0pXG5leHBvcnQgY2xhc3MgTWRsTWVudVJlZ2lzdHkge1xuICBtZW51Q29tcG9uZW50czogTWRsTWVudUNvbXBvbmVudFtdID0gW107XG5cbiAgYWRkKG1lbnVDb21wb25lbnQ6IE1kbE1lbnVDb21wb25lbnQpOiB2b2lkIHtcbiAgICB0aGlzLm1lbnVDb21wb25lbnRzLnB1c2gobWVudUNvbXBvbmVudCk7XG4gIH1cblxuICByZW1vdmUobWVudUNvbXBvbmVudDogTWRsTWVudUNvbXBvbmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGZyb21JbmRleCA9IHRoaXMubWVudUNvbXBvbmVudHMuaW5kZXhPZihtZW51Q29tcG9uZW50KTtcbiAgICB0aGlzLm1lbnVDb21wb25lbnRzLnNwbGljZShmcm9tSW5kZXgsIDEpO1xuICB9XG5cbiAgaGlkZUFsbEV4Y2VwdChtZW51Q29tcG9uZW50OiBNZGxNZW51Q29tcG9uZW50KTogdm9pZCB7XG4gICAgdGhpcy5tZW51Q29tcG9uZW50cy5mb3JFYWNoKChjb21wb25lbnQpID0+IHtcbiAgICAgIGlmIChjb21wb25lbnQgIT09IG1lbnVDb21wb25lbnQpIHtcbiAgICAgICAgY29tcG9uZW50LmhpZGUoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwibWRsLW1lbnVcIixcbiAgZXhwb3J0QXM6IFwibWRsTWVudVwiLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgI2NvbnRhaW5lciBjbGFzcz1cIm1kbC1tZW51X19jb250YWluZXIgaXMtdXBncmFkZWRcIj5cbiAgICAgIDxkaXYgI291dGxpbmUgY2xhc3M9XCJtZGwtbWVudV9fb3V0bGluZVwiIFtuZ0NsYXNzXT1cImNzc1Bvc2l0aW9uXCI+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwibWRsLW1lbnVcIiAjbWVudUVsZW1lbnQ+XG4gICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxufSlcbmV4cG9ydCBjbGFzcyBNZGxNZW51Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgQElucHV0KFwibWRsLW1lbnUtcG9zaXRpb25cIilcbiAgcG9zaXRpb246IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBAVmlld0NoaWxkKFwiY29udGFpbmVyXCIsIHsgc3RhdGljOiB0cnVlIH0pXG4gIGNvbnRhaW5lckNoaWxkOiBFbGVtZW50UmVmIHwgdW5kZWZpbmVkO1xuICBAVmlld0NoaWxkKFwibWVudUVsZW1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSlcbiAgbWVudUVsZW1lbnRDaGlsZDogRWxlbWVudFJlZiB8IHVuZGVmaW5lZDtcbiAgQFZpZXdDaGlsZChcIm91dGxpbmVcIiwgeyBzdGF0aWM6IHRydWUgfSlcbiAgb3V0bGluZUNoaWxkOiBFbGVtZW50UmVmIHwgdW5kZWZpbmVkO1xuXG4gIHB1YmxpYyBjc3NQb3NpdGlvbiA9IFwibWRsLW1lbnUtLWJvdHRvbS1sZWZ0XCI7XG4gIHByaXZhdGUgY29udGFpbmVyOiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBtZW51RWxlbWVudDogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgb3V0bGluZTogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgaXNWaXNpYmxlID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIHByaXZhdGUgbWVudVJlZ2lzdHJ5OiBNZGxNZW51UmVnaXN0eVxuICApIHtcbiAgICB0aGlzLm1lbnVSZWdpc3RyeS5hZGQodGhpcyk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmNzc1Bvc2l0aW9uID0gQ1NTX0FMSUdOX01BUFt0aGlzLnBvc2l0aW9uID8/IEJPVFRPTV9MRUZUXTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyQ2hpbGQ/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgdGhpcy5tZW51RWxlbWVudCA9IHRoaXMubWVudUVsZW1lbnRDaGlsZD8ubmF0aXZlRWxlbWVudDtcbiAgICB0aGlzLm91dGxpbmUgPSB0aGlzLm91dGxpbmVDaGlsZD8ubmF0aXZlRWxlbWVudDtcblxuICAgIC8vIEFkZCBhIGNsaWNrIGxpc3RlbmVyIHRvIHRoZSBkb2N1bWVudCwgdG8gY2xvc2UgdGhlIG1lbnUuXG4gICAgY29uc3QgY2FsbGJhY2sgPSAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5pc1Zpc2libGUpIHtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFwid2luZG93XCIsIFwiY2xpY2tcIiwgY2FsbGJhY2spO1xuICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFwid2luZG93XCIsIFwidG91Y2hzdGFydFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICB0b2dnbGUoZXZlbnQ6IEV2ZW50LCBtZGxCdXR0b246IE1kbEJ1dHRvbkNvbXBvbmVudCk6IHZvaWQge1xuICAgIGlmICghbWRsQnV0dG9uKSB7XG4gICAgICB0aHJvdyBuZXcgTWRsTWVudUVycm9yKGBNZGxCdXR0b25Db21wb25lbnQgaXMgcmVxdWlyZWRgKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuaXNWaXNpYmxlKSB7XG4gICAgICB0aGlzLmhpZGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zaG93KGV2ZW50LCBtZGxCdXR0b24pO1xuICAgIH1cbiAgfVxuXG4gIGhpZGVPbkl0ZW1DbGlja2VkKCk6IHZvaWQge1xuICAgIC8vIFdhaXQgc29tZSB0aW1lIGJlZm9yZSBjbG9zaW5nIG1lbnUsIHNvIHRoZSB1c2VyIGNhbiBzZWUgdGhlIHJpcHBsZS5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuaGlkZSgpO1xuICAgIH0sIENMT1NFX1RJTUVPVVQpO1xuICB9XG5cbiAgaGlkZSgpOiB2b2lkIHtcbiAgICAvLyBSZW1vdmUgYWxsIHRyYW5zaXRpb24gZGVsYXlzOyBtZW51IGl0ZW1zIGZhZGUgb3V0IGNvbmN1cnJlbnRseS5cbiAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFwibWRsLW1lbnUtaXRlbVwiKS5mb3JFYWNoKChlbCkgPT4ge1xuICAgICAgKGVsIGFzIEhUTUxFbGVtZW50KS5zdHlsZS5yZW1vdmVQcm9wZXJ0eShcInRyYW5zaXRpb24tZGVsYXlcIik7XG4gICAgfSk7XG4gICAgLy8gdGhpcy5tZW51SXRlbUNvbXBvbmVudHMudG9BcnJheSgpLmZvckVhY2gobWkgPT4ge1xuICAgIC8vICAgbWkuZWxlbWVudC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgndHJhbnNpdGlvbi1kZWxheScpO1xuICAgIC8vIH0pO1xuXG4gICAgLy8gTWVhc3VyZSB0aGUgaW5uZXIgZWxlbWVudC5cbiAgICBjb25zdCByZWN0ID0gdGhpcy5tZW51RWxlbWVudD8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgaGVpZ2h0ID0gcmVjdD8uaGVpZ2h0O1xuICAgIGNvbnN0IHdpZHRoID0gcmVjdD8ud2lkdGg7XG5cbiAgICAvLyBUdXJuIG9uIGFuaW1hdGlvbiwgYW5kIGFwcGx5IHRoZSBmaW5hbCBjbGlwLiBBbHNvIG1ha2UgaW52aXNpYmxlLlxuICAgIC8vIFRoaXMgdHJpZ2dlcnMgdGhlIHRyYW5zaXRpb25zLlxuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5tZW51RWxlbWVudCwgXCJpcy1hbmltYXRpbmdcIik7XG4gICAgdGhpcy5hcHBseUNsaXAoaGVpZ2h0LCB3aWR0aCk7XG4gICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyh0aGlzLmNvbnRhaW5lciwgXCJpcy12aXNpYmxlXCIpO1xuXG4gICAgLy8gQ2xlYW4gdXAgYWZ0ZXIgdGhlIGFuaW1hdGlvbiBpcyBjb21wbGV0ZS5cbiAgICB0aGlzLmFkZEFuaW1hdGlvbkVuZExpc3RlbmVyKCk7XG5cbiAgICB0aGlzLmlzVmlzaWJsZSA9IGZhbHNlO1xuICB9XG5cbiAgc2hvdyhldmVudDogRXZlbnQsIG1kbEJ1dHRvbjogTWRsQnV0dG9uQ29tcG9uZW50KTogdm9pZCB7XG4gICAgdGhpcy5tZW51UmVnaXN0cnkuaGlkZUFsbEV4Y2VwdCh0aGlzKTtcblxuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgY29uc3QgZm9yRWxlbWVudCA9IG1kbEJ1dHRvbi5lbGVtZW50O1xuICAgIGNvbnN0IHJlY3QgPSBmb3JFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGNvbnN0IGZvclJlY3QgPSBmb3JFbGVtZW50Py5wYXJlbnRFbGVtZW50Py5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIGlmICghdGhpcy5jb250YWluZXIgfHwgIWZvclJlY3QpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMucG9zaXRpb24gPT09IFVOQUxJR05FRCkge1xuICAgICAgLy8gRG8gbm90IHBvc2l0aW9uIHRoZSBtZW51IGF1dG9tYXRpY2FsbHkuIFJlcXVpcmVzIHRoZSBkZXZlbG9wZXIgdG9cbiAgICAgIC8vIG1hbnVhbGx5IHNwZWNpZnkgcG9zaXRpb24uXG4gICAgfSBlbHNlIGlmICh0aGlzLnBvc2l0aW9uID09PSBCT1RUT01fUklHSFQpIHtcbiAgICAgIC8vIFBvc2l0aW9uIGJlbG93IHRoZSBcImZvclwiIGVsZW1lbnQsIGFsaWduZWQgdG8gaXRzIHJpZ2h0LlxuICAgICAgdGhpcy5jb250YWluZXIuc3R5bGUucmlnaHQgPSBmb3JSZWN0LnJpZ2h0IC0gcmVjdC5yaWdodCArIFwicHhcIjtcbiAgICAgIHRoaXMuY29udGFpbmVyLnN0eWxlLnRvcCA9XG4gICAgICAgIGZvckVsZW1lbnQub2Zmc2V0VG9wICsgZm9yRWxlbWVudC5vZmZzZXRIZWlnaHQgKyBcInB4XCI7XG4gICAgfSBlbHNlIGlmICh0aGlzLnBvc2l0aW9uID09PSBUT1BfTEVGVCkge1xuICAgICAgLy8gUG9zaXRpb24gYWJvdmUgdGhlIFwiZm9yXCIgZWxlbWVudCwgYWxpZ25lZCB0byBpdHMgbGVmdC5cbiAgICAgIHRoaXMuY29udGFpbmVyLnN0eWxlLmxlZnQgPSBmb3JFbGVtZW50Lm9mZnNldExlZnQgKyBcInB4XCI7XG4gICAgICB0aGlzLmNvbnRhaW5lci5zdHlsZS5ib3R0b20gPSBmb3JSZWN0LmJvdHRvbSAtIHJlY3QudG9wICsgXCJweFwiO1xuICAgIH0gZWxzZSBpZiAodGhpcy5wb3NpdGlvbiA9PT0gVE9QX1JJR0hUKSB7XG4gICAgICAvLyBQb3NpdGlvbiBhYm92ZSB0aGUgXCJmb3JcIiBlbGVtZW50LCBhbGlnbmVkIHRvIGl0cyByaWdodC5cbiAgICAgIHRoaXMuY29udGFpbmVyLnN0eWxlLnJpZ2h0ID0gZm9yUmVjdC5yaWdodCAtIHJlY3QucmlnaHQgKyBcInB4XCI7XG4gICAgICB0aGlzLmNvbnRhaW5lci5zdHlsZS5ib3R0b20gPSBmb3JSZWN0LmJvdHRvbSAtIHJlY3QudG9wICsgXCJweFwiO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZWZhdWx0OiBwb3NpdGlvbiBiZWxvdyB0aGUgXCJmb3JcIiBlbGVtZW50LCBhbGlnbmVkIHRvIGl0cyBsZWZ0LlxuICAgICAgdGhpcy5jb250YWluZXIuc3R5bGUubGVmdCA9IGZvckVsZW1lbnQub2Zmc2V0TGVmdCArIFwicHhcIjtcbiAgICAgIHRoaXMuY29udGFpbmVyLnN0eWxlLnRvcCA9XG4gICAgICAgIGZvckVsZW1lbnQub2Zmc2V0VG9wICsgZm9yRWxlbWVudC5vZmZzZXRIZWlnaHQgKyBcInB4XCI7XG4gICAgfVxuXG4gICAgLy8gTWVhc3VyZSB0aGUgaW5uZXIgZWxlbWVudC5cbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLm1lbnVFbGVtZW50Py5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgPz8gMDtcbiAgICBjb25zdCB3aWR0aCA9IHRoaXMubWVudUVsZW1lbnQ/LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoID8/IDA7XG5cbiAgICB0aGlzLmNvbnRhaW5lci5zdHlsZS53aWR0aCA9IHdpZHRoICsgXCJweFwiO1xuICAgIHRoaXMuY29udGFpbmVyLnN0eWxlLmhlaWdodCA9IGhlaWdodCArIFwicHhcIjtcbiAgICBpZiAodGhpcy5vdXRsaW5lKSB7XG4gICAgICB0aGlzLm91dGxpbmUuc3R5bGUud2lkdGggPSB3aWR0aCArIFwicHhcIjtcbiAgICAgIHRoaXMub3V0bGluZS5zdHlsZS5oZWlnaHQgPSBoZWlnaHQgKyBcInB4XCI7XG4gICAgfVxuXG4gICAgY29uc3QgdHJhbnNpdGlvbkR1cmF0aW9uID1cbiAgICAgIFRSQU5TSVRJT05fRFVSQVRJT05fU0VDT05EUyAqIFRSQU5TSVRJT05fRFVSQVRJT05fRlJBQ1RJT047XG4gICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChcIm1kbC1tZW51LWl0ZW1cIikuZm9yRWFjaCgoZWwpID0+IHtcbiAgICAgIGNvbnN0IG1pID0gZWwgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICBsZXQgaXRlbURlbGF5O1xuICAgICAgaWYgKHRoaXMucG9zaXRpb24gPT09IFRPUF9MRUZUIHx8IHRoaXMucG9zaXRpb24gPT09IFRPUF9SSUdIVCkge1xuICAgICAgICBpdGVtRGVsYXkgPVxuICAgICAgICAgICgoaGVpZ2h0IC0gbWkub2Zmc2V0VG9wIC0gbWkub2Zmc2V0SGVpZ2h0KSAvIGhlaWdodCkgKlxuICAgICAgICAgICAgdHJhbnNpdGlvbkR1cmF0aW9uICtcbiAgICAgICAgICBcInNcIjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGl0ZW1EZWxheSA9IChtaS5vZmZzZXRUb3AgLyBoZWlnaHQpICogdHJhbnNpdGlvbkR1cmF0aW9uICsgXCJzXCI7XG4gICAgICB9XG4gICAgICBtaS5zdHlsZS50cmFuc2l0aW9uRGVsYXkgPSBpdGVtRGVsYXk7XG4gICAgfSk7XG5cbiAgICAvLyBBcHBseSB0aGUgaW5pdGlhbCBjbGlwIHRvIHRoZSB0ZXh0IGJlZm9yZSB3ZSBzdGFydCBhbmltYXRpbmcuXG4gICAgdGhpcy5hcHBseUNsaXAoaGVpZ2h0LCB3aWR0aCk7XG5cbiAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuY29udGFpbmVyLCBcImlzLXZpc2libGVcIik7XG4gICAgaWYgKHRoaXMubWVudUVsZW1lbnQpIHtcbiAgICAgIHRoaXMubWVudUVsZW1lbnQuc3R5bGUuY2xpcCA9XG4gICAgICAgIFwicmVjdCgwIFwiICsgd2lkdGggKyBcInB4IFwiICsgaGVpZ2h0ICsgXCJweCAwKVwiO1xuICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLm1lbnVFbGVtZW50LCBcImlzLWFuaW1hdGluZ1wiKTtcbiAgICB9XG5cbiAgICB0aGlzLmFkZEFuaW1hdGlvbkVuZExpc3RlbmVyKCk7XG5cbiAgICB0aGlzLmlzVmlzaWJsZSA9IHRydWU7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLm1lbnVSZWdpc3RyeS5yZW1vdmUodGhpcyk7XG4gIH1cblxuICBwcml2YXRlIGFkZEFuaW1hdGlvbkVuZExpc3RlbmVyKCkge1xuICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKHRoaXMubWVudUVsZW1lbnQsIFwidHJhbnNpdGlvbmVuZFwiLCAoKSA9PiB7XG4gICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMubWVudUVsZW1lbnQsIFwiaXMtYW5pbWF0aW5nXCIpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFwcGx5Q2xpcChoZWlnaHQ6IG51bWJlciB8IHVuZGVmaW5lZCwgd2lkdGg6IG51bWJlciB8IHVuZGVmaW5lZCkge1xuICAgIGlmICghdGhpcy5tZW51RWxlbWVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5wb3NpdGlvbiA9PT0gVU5BTElHTkVEKSB7XG4gICAgICAvLyBEbyBub3QgY2xpcC5cbiAgICAgIHRoaXMubWVudUVsZW1lbnQuc3R5bGUuY2xpcCA9IFwiXCI7XG4gICAgfSBlbHNlIGlmICh0aGlzLnBvc2l0aW9uID09PSBCT1RUT01fUklHSFQpIHtcbiAgICAgIC8vIENsaXAgdG8gdGhlIHRvcCByaWdodCBjb3JuZXIgb2YgdGhlIG1lbnUuXG4gICAgICB0aGlzLm1lbnVFbGVtZW50LnN0eWxlLmNsaXAgPVxuICAgICAgICBcInJlY3QoMCBcIiArIHdpZHRoICsgXCJweCBcIiArIFwiMCBcIiArIHdpZHRoICsgXCJweClcIjtcbiAgICB9IGVsc2UgaWYgKHRoaXMucG9zaXRpb24gPT09IFRPUF9MRUZUKSB7XG4gICAgICAvLyBDbGlwIHRvIHRoZSBib3R0b20gbGVmdCBjb3JuZXIgb2YgdGhlIG1lbnUuXG4gICAgICB0aGlzLm1lbnVFbGVtZW50LnN0eWxlLmNsaXAgPVxuICAgICAgICBcInJlY3QoXCIgKyBoZWlnaHQgKyBcInB4IDAgXCIgKyBoZWlnaHQgKyBcInB4IDApXCI7XG4gICAgfSBlbHNlIGlmICh0aGlzLnBvc2l0aW9uID09PSBUT1BfUklHSFQpIHtcbiAgICAgIC8vIENsaXAgdG8gdGhlIGJvdHRvbSByaWdodCBjb3JuZXIgb2YgdGhlIG1lbnUuXG4gICAgICB0aGlzLm1lbnVFbGVtZW50LnN0eWxlLmNsaXAgPVxuICAgICAgICBcInJlY3QoXCIgK1xuICAgICAgICBoZWlnaHQgK1xuICAgICAgICBcInB4IFwiICtcbiAgICAgICAgd2lkdGggK1xuICAgICAgICBcInB4IFwiICtcbiAgICAgICAgaGVpZ2h0ICtcbiAgICAgICAgXCJweCBcIiArXG4gICAgICAgIHdpZHRoICtcbiAgICAgICAgXCJweClcIjtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVmYXVsdDogZG8gbm90IGNsaXAgKHNhbWUgYXMgY2xpcHBpbmcgdG8gdGhlIHRvcCBsZWZ0IGNvcm5lcikuXG4gICAgICB0aGlzLm1lbnVFbGVtZW50LnN0eWxlLmNsaXAgPSBcIlwiO1xuICAgIH1cbiAgfVxufVxuIl19