UNPKG

@looorent/ngx-simple-modal

Version:

A simple unopinionated framework to implement simple modal based behaviour in angular (v2+) projects.

222 lines 27 kB
import { Component, Inject, ViewContainerRef, ViewChild } from '@angular/core'; import { of } from 'rxjs'; import { DefaultSimpleModalOptionConfig } from './simple-modal-options'; import { SimpleModalWrapperComponent } from './simple-modal-wrapper.component'; import { DraggableDirective } from './simple-modal-draggable.directive'; import * as i0 from "@angular/core"; /** * View container manager which manages a list of modals currently active * inside the viewvontainer */ class SimpleModalHolderComponent { resolver; renderer; ngZone; defaultSimpleModalOptions; /** * Target viewContainer to insert modals */ viewContainer; /** * modal collection, maintained by addModal and removeModal * @type {Array<SimpleModalComponent> } */ modals = []; /** * if auto focus is on and no element focused, store it here to be restored back after close */ previousActiveElement = null; /** * Constructor * @param {ComponentFactoryResolver} resolver * @param renderer * @param ngZone * @param defaultSimpleModalOptions */ constructor(resolver, renderer, ngZone, defaultSimpleModalOptions) { this.resolver = resolver; this.renderer = renderer; this.ngZone = ngZone; this.defaultSimpleModalOptions = defaultSimpleModalOptions; } /** * Configures then adds modal to the modals array, and populates with data passed in * @param {Type<SimpleModalComponent>} component * @param {object?} data * @param {SimpleModalOptionsOverrides?} options * @return {Observable<*>} */ addModal(component, data, options) { // create component if (!this.viewContainer) { return of(null); } const factory = this.resolver.resolveComponentFactory(SimpleModalWrapperComponent); const componentRef = this.viewContainer.createComponent(factory); const modalWrapper = (componentRef.instance); const { ref: _componentRef, component: _component } = modalWrapper.addComponent(component); // assign options refs _component.options = options = Object.assign({}, this.defaultSimpleModalOptions, options); // set base classes for wrapper modalWrapper.modalClasses = options.wrapperDefaultClasses; // add to stack this.modals.push(_component); // wait a tick then setup the following while adding a modal this.wait().then(() => { this.toggleWrapperClass(modalWrapper.wrapper, options.wrapperClass); this.toggleBodyClass(options.bodyClass); if (options.draggable) { this.setDraggable(_componentRef, options); } this.wait(options.animationDuration).then(() => { this.autoFocusFirstElement(_component.wrapper, options.autoFocus); _component.markAsReady(); }); }); // when closing modal remove it _component.onClosing(modal => this.removeModal(modal)); // if clicking on background closes modal this.configureCloseOnClickOutside(modalWrapper); // map and return observable _component.mapDataObject(data); return _component.setupObserver(); } /** * triggers components close function * to take effect * @returns {Promise<void>} * @param closingModal */ removeModal(closingModal) { const options = closingModal.options; this.toggleWrapperClass(closingModal.wrapper, options.wrapperClass); return this.wait(options.animationDuration).then(() => { this.removeModalFromArray(closingModal); this.toggleBodyClass(options.bodyClass); this.restorePreviousFocus(); }); } /** * Instructs all open modals to */ removeAllModals() { return Promise.all(this.modals.map(modal => this.removeModal(modal))); } /** * Bind a body class 'modal-open' to a condition of modals in pool > 0 * @param bodyClass - string to add and remove from body in document */ toggleBodyClass(bodyClass) { if (!bodyClass) { return; } const body = document.getElementsByTagName('body')[0]; const bodyClassItems = bodyClass.split(' '); if (!this.modals.length) { body.classList.remove(...bodyClassItems); } else { body.classList.add(...bodyClassItems); } } /** * if the option to close on background click is set, then hook up a callback * @param modalWrapper */ configureCloseOnClickOutside(modalWrapper) { modalWrapper.onClickOutsideModalContent(() => { if (modalWrapper.content.options.closeOnClickOutside) { modalWrapper.content.close(); } }); } /** * Auto focus o the first element if autofocus is on * @param componentWrapper * @param autoFocus */ autoFocusFirstElement(componentWrapper, autoFocus) { if (autoFocus) { const focusable = componentWrapper.nativeElement.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); if (focusable && focusable.length) { this.previousActiveElement = document.activeElement; focusable[0].focus(); } } } /** * Restores the last focus is there was one */ restorePreviousFocus() { if (this.previousActiveElement) { this.previousActiveElement.focus(); this.previousActiveElement = null; } } /** * Configure the adding and removal of a wrapper class - predominantly animation focused * @param modalWrapperEl * @param wrapperClass */ toggleWrapperClass(modalWrapperEl, wrapperClass) { const wrapperClassList = modalWrapperEl.nativeElement.classList; const wrapperClassItems = wrapperClass.split(' '); if (wrapperClassList.toString().indexOf(wrapperClass) !== -1) { wrapperClassList.remove(...wrapperClassItems); } else { wrapperClassList.add(...wrapperClassItems); } } /** * Enables the drag option on the modal if the options have it enabled * @param component * @param options * @private */ setDraggable(component, options) { const draggableDirective = new DraggableDirective(component.location, this.ngZone, this.renderer); draggableDirective.dragTarget = component.location.nativeElement; draggableDirective.dragHandle = component.instance.handle ? component.instance.handle.nativeElement : undefined; draggableDirective.ngAfterViewInit(); component.location.nativeElement.classList.add(options.draggableClass); } /** * Helper function for a more readable timeout * @param ms */ wait(ms = 0) { return new Promise((resolve, reject) => { setTimeout(() => resolve(undefined), ms); }); } /** * Instructs the holder to remove the modal and * removes this component from the collection * @param {SimpleModalComponent} component */ removeModalFromArray(component) { const index = this.modals.indexOf(component); if (index > -1) { this.viewContainer.remove(index); this.modals.splice(index, 1); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.3", ngImport: i0, type: SimpleModalHolderComponent, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: DefaultSimpleModalOptionConfig }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.3", type: SimpleModalHolderComponent, selector: "simple-modal-holder", viewQueries: [{ propertyName: "viewContainer", first: true, predicate: ["viewContainer"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: '<ng-template #viewContainer></ng-template>', isInline: true }); } export { SimpleModalHolderComponent }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.3", ngImport: i0, type: SimpleModalHolderComponent, decorators: [{ type: Component, args: [{ selector: 'simple-modal-holder', template: '<ng-template #viewContainer></ng-template>', }] }], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: undefined, decorators: [{ type: Inject, args: [DefaultSimpleModalOptionConfig] }] }]; }, propDecorators: { viewContainer: [{ type: ViewChild, args: ['viewContainer', { read: ViewContainerRef, static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlLW1vZGFsLWhvbGRlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2ltcGxlLW1vZGFsL3NpbXBsZS1tb2RhbC1ob2xkZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQXdDLE1BQU0sRUFBUSxnQkFBZ0IsRUFBRSxTQUFTLEVBQW1DLE1BQU0sZUFBZSxDQUFDO0FBQzVKLE9BQU8sRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLDhCQUE4QixFQUFtRCxNQUFNLHdCQUF3QixDQUFDO0FBQ3pILE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRS9FLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDOztBQUV4RTs7O0dBR0c7QUFDSCxNQUlhLDBCQUEwQjtJQXlCM0I7SUFDQTtJQUNBO0lBQ3dDO0lBM0JsRDs7T0FFRztJQUNtRSxhQUFhLENBQUM7SUFFcEY7OztPQUdHO0lBQ0gsTUFBTSxHQUEwQyxFQUFFLENBQUM7SUFFbkQ7O09BRUc7SUFDSCxxQkFBcUIsR0FBRyxJQUFJLENBQUM7SUFFN0I7Ozs7OztPQU1HO0lBQ0gsWUFDVSxRQUFrQyxFQUNsQyxRQUFtQixFQUNuQixNQUFjLEVBQzBCLHlCQUE2QztRQUhyRixhQUFRLEdBQVIsUUFBUSxDQUEwQjtRQUNsQyxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQ25CLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDMEIsOEJBQXlCLEdBQXpCLHlCQUF5QixDQUFvQjtJQUUvRixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsUUFBUSxDQUNOLFNBQTRDLEVBQzVDLElBQVEsRUFDUixPQUFxQztRQUVyQyxtQkFBbUI7UUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUU7WUFDdkIsT0FBTyxFQUFFLENBQUMsSUFB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UmVzb2x2ZXIsIEVsZW1lbnRSZWYsIEluamVjdCwgVHlwZSwgVmlld0NvbnRhaW5lclJlZiwgVmlld0NoaWxkLCBSZW5kZXJlcjIsIENvbXBvbmVudFJlZiwgTmdab25lIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgRGVmYXVsdFNpbXBsZU1vZGFsT3B0aW9uQ29uZmlnLCBTaW1wbGVNb2RhbE9wdGlvbnMsIFNpbXBsZU1vZGFsT3B0aW9uc092ZXJyaWRlcyB9IGZyb20gJy4vc2ltcGxlLW1vZGFsLW9wdGlvbnMnO1xuaW1wb3J0IHsgU2ltcGxlTW9kYWxXcmFwcGVyQ29tcG9uZW50IH0gZnJvbSAnLi9zaW1wbGUtbW9kYWwtd3JhcHBlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2ltcGxlTW9kYWxDb21wb25lbnQgfSBmcm9tICcuL3NpbXBsZS1tb2RhbC5jb21wb25lbnQnO1xuaW1wb3J0IHsgRHJhZ2dhYmxlRGlyZWN0aXZlIH0gZnJvbSAnLi9zaW1wbGUtbW9kYWwtZHJhZ2dhYmxlLmRpcmVjdGl2ZSc7XG5cbi8qKlxuICogVmlldyBjb250YWluZXIgbWFuYWdlciB3aGljaCBtYW5hZ2VzIGEgbGlzdCBvZiBtb2RhbHMgY3VycmVudGx5IGFjdGl2ZVxuICogaW5zaWRlIHRoZSB2aWV3dm9udGFpbmVyXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3NpbXBsZS1tb2RhbC1ob2xkZXInLFxuICB0ZW1wbGF0ZTogJzxuZy10ZW1wbGF0ZSAjdmlld0NvbnRhaW5lcj48L25nLXRlbXBsYXRlPicsXG59KVxuZXhwb3J0IGNsYXNzIFNpbXBsZU1vZGFsSG9sZGVyQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIFRhcmdldCB2aWV3Q29udGFpbmVyIHRvIGluc2VydCBtb2RhbHNcbiAgICovXG4gIEBWaWV3Q2hpbGQoJ3ZpZXdDb250YWluZXInLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYsIHN0YXRpYzogdHJ1ZSB9KSB2aWV3Q29udGFpbmVyO1xuXG4gIC8qKlxuICAgKiBtb2RhbCBjb2xsZWN0aW9uLCBtYWludGFpbmVkIGJ5IGFkZE1vZGFsIGFuZCByZW1vdmVNb2RhbFxuICAgKiBAdHlwZSB7QXJyYXk8U2ltcGxlTW9kYWxDb21wb25lbnQ+IH1cbiAgICovXG4gIG1vZGFsczogQXJyYXk8U2ltcGxlTW9kYWxDb21wb25lbnQ8YW55LCBhbnk+PiA9IFtdO1xuXG4gIC8qKlxuICAgKiBpZiBhdXRvIGZvY3VzIGlzIG9uIGFuZCBubyBlbGVtZW50IGZvY3VzZWQsIHN0b3JlIGl0IGhlcmUgdG8gYmUgcmVzdG9yZWQgYmFjayBhZnRlciBjbG9zZVxuICAgKi9cbiAgcHJldmlvdXNBY3RpdmVFbGVtZW50ID0gbnVsbDtcblxuICAvKipcbiAgICogQ29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXJ9IHJlc29sdmVyXG4gICAqIEBwYXJhbSByZW5kZXJlclxuICAgKiBAcGFyYW0gbmdab25lXG4gICAqIEBwYXJhbSBkZWZhdWx0U2ltcGxlTW9kYWxPcHRpb25zXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlc29sdmVyOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmUsXG4gICAgQEluamVjdChEZWZhdWx0U2ltcGxlTW9kYWxPcHRpb25Db25maWcpIHByaXZhdGUgZGVmYXVsdFNpbXBsZU1vZGFsT3B0aW9uczogU2ltcGxlTW9kYWxPcHRpb25zLFxuICApIHtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmVzIHRoZW4gYWRkcyBtb2RhbCB0byB0aGUgbW9kYWxzIGFycmF5LCBhbmQgcG9wdWxhdGVzIHdpdGggZGF0YSBwYXNzZWQgaW5cbiAgICogQHBhcmFtIHtUeXBlPFNpbXBsZU1vZGFsQ29tcG9uZW50Pn0gY29tcG9uZW50XG4gICAqIEBwYXJhbSB7b2JqZWN0P30gZGF0YVxuICAgKiBAcGFyYW0ge1NpbXBsZU1vZGFsT3B0aW9uc092ZXJyaWRlcz99IG9wdGlvbnNcbiAgICogQHJldHVybiB7T2JzZXJ2YWJsZTwqPn1cbiAgICovXG4gIGFkZE1vZGFsPFQsIFQxPihcbiAgICBjb21wb25lbnQ6IFR5cGU8U2ltcGxlTW9kYWxDb21wb25lbnQ8VCwgVDE+PixcbiAgICBkYXRhPzogVCxcbiAgICBvcHRpb25zPzogU2ltcGxlTW9kYWxPcHRpb25zT3ZlcnJpZGVzLFxuICApOiBPYnNlcnZhYmxlPFQxPiB7XG4gICAgLy8gY3JlYXRlIGNvbXBvbmVudFxuICAgIGlmICghdGhpcy52aWV3Q29udGFpbmVyKSB7XG4gICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgfVxuICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLnJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KFNpbXBsZU1vZGFsV3JhcHBlckNvbXBvbmVudCk7XG4gICAgY29uc3QgY29tcG9uZW50UmVmID0gdGhpcy52aWV3Q29udGFpbmVyLmNyZWF0ZUNvbXBvbmVudChmYWN0b3J5KTtcbiAgICBjb25zdCBtb2RhbFdyYXBwZXI6IFNpbXBsZU1vZGFsV3JhcHBlckNvbXBvbmVudCA9IDxTaW1wbGVNb2RhbFdyYXBwZXJDb21wb25lbnQ+KFxuICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlXG4gICAgKTtcbiAgICBjb25zdCB7IHJlZjogX2NvbXBvbmVudFJlZiwgY29tcG9uZW50OiBfY29tcG9uZW50IH0gPSBtb2RhbFdyYXBwZXIuYWRkQ29tcG9uZW50KGNvbXBvbmVudCk7XG5cbiAgICAvLyBhc3NpZ24gb3B0aW9ucyByZWZzXG4gICAgX2NvbXBvbmVudC5vcHRpb25zID0gb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZGVmYXVsdFNpbXBsZU1vZGFsT3B0aW9ucywgb3B0aW9ucykgYXMgU2ltcGxlTW9kYWxPcHRpb25zO1xuXG4gICAgLy8gc2V0IGJhc2UgY2xhc3NlcyBmb3Igd3JhcHBlclxuICAgIG1vZGFsV3JhcHBlci5tb2RhbENsYXNzZXMgPSBvcHRpb25zLndyYXBwZXJEZWZhdWx0Q2xhc3NlcztcblxuICAgIC8vIGFkZCB0byBzdGFja1xuICAgIHRoaXMubW9kYWxzLnB1c2goX2NvbXBvbmVudCk7XG5cbiAgICAvLyB3YWl0IGEgdGljayB0aGVuIHNldHVwIHRoZSBmb2xsb3dpbmcgd2hpbGUgYWRkaW5nIGEgbW9kYWxcbiAgICB0aGlzLndhaXQoKS50aGVuKCgpID0+IHtcbiAgICAgIHRoaXMudG9nZ2xlV3JhcHBlckNsYXNzKG1vZGFsV3JhcHBlci53cmFwcGVyLCBvcHRpb25zLndyYXBwZXJDbGFzcyk7XG4gICAgICB0aGlzLnRvZ2dsZUJvZHlDbGFzcyhvcHRpb25zLmJvZHlDbGFzcyk7XG4gICAgICBpZiAob3B0aW9ucy5kcmFnZ2FibGUpIHtcbiAgICAgICAgdGhpcy5zZXREcmFnZ2FibGUoX2NvbXBvbmVudFJlZiwgb3B0aW9ucyk7XG4gICAgICB9XG4gICAgICB0aGlzLndhaXQob3B0aW9ucy5hbmltYXRpb25EdXJhdGlvbikudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuYXV0b0ZvY3VzRmlyc3RFbGVtZW50KF9jb21wb25lbnQud3JhcHBlciwgb3B0aW9ucy5hdXRvRm9jdXMpO1xuICAgICAgICBfY29tcG9uZW50Lm1hcmtBc1JlYWR5KCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIHdoZW4gY2xvc2luZyBtb2RhbCByZW1vdmUgaXRcbiAgICBfY29tcG9uZW50Lm9uQ2xvc2luZyhtb2RhbCA9PiB0aGlzLnJlbW92ZU1vZGFsKG1vZGFsKSk7XG5cbiAgICAvLyBpZiBjbGlja2luZyBvbiBiYWNrZ3JvdW5kIGNsb3NlcyBtb2RhbFxuICAgIHRoaXMuY29uZmlndXJlQ2xvc2VPbkNsaWNrT3V0c2lkZShtb2RhbFdyYXBwZXIpO1xuXG4gICAgLy8gbWFwIGFuZCByZXR1cm4gb2JzZXJ2YWJsZVxuICAgIF9jb21wb25lbnQubWFwRGF0YU9iamVjdChkYXRhKTtcblxuICAgIHJldHVybiBfY29tcG9uZW50LnNldHVwT2JzZXJ2ZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiB0cmlnZ2VycyBjb21wb25lbnRzIGNsb3NlIGZ1bmN0aW9uXG4gICAqIHRvIHRha2UgZWZmZWN0XG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKiBAcGFyYW0gY2xvc2luZ01vZGFsXG4gICAqL1xuICByZW1vdmVNb2RhbChjbG9zaW5nTW9kYWw6IFNpbXBsZU1vZGFsQ29tcG9uZW50PGFueSwgYW55Pik6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IGNsb3NpbmdNb2RhbC5vcHRpb25zO1xuICAgIHRoaXMudG9nZ2xlV3JhcHBlckNsYXNzKGNsb3NpbmdNb2RhbC53cmFwcGVyLCBvcHRpb25zLndyYXBwZXJDbGFzcyk7XG4gICAgcmV0dXJuIHRoaXMud2FpdChvcHRpb25zLmFuaW1hdGlvbkR1cmF0aW9uKS50aGVuKCgpID0+IHtcbiAgICAgIHRoaXMucmVtb3ZlTW9kYWxGcm9tQXJyYXkoY2xvc2luZ01vZGFsKTtcbiAgICAgIHRoaXMudG9nZ2xlQm9keUNsYXNzKG9wdGlvbnMuYm9keUNsYXNzKTtcbiAgICAgIHRoaXMucmVzdG9yZVByZXZpb3VzRm9jdXMoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnN0cnVjdHMgYWxsIG9wZW4gbW9kYWxzIHRvXG4gICAqL1xuICByZW1vdmVBbGxNb2RhbHMoKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwodGhpcy5tb2RhbHMubWFwKG1vZGFsID0+IHRoaXMucmVtb3ZlTW9kYWwobW9kYWwpKSk7XG4gIH1cblxuICAvKipcbiAgICogQmluZCBhIGJvZHkgY2xhc3MgJ21vZGFsLW9wZW4nIHRvIGEgY29uZGl0aW9uIG9mIG1vZGFscyBpbiBwb29sID4gMFxuICAgKiBAcGFyYW0gYm9keUNsYXNzIC0gc3RyaW5nIHRvIGFkZCBhbmQgcmVtb3ZlIGZyb20gYm9keSBpbiBkb2N1bWVudFxuICAgKi9cbiAgcHJpdmF0ZSB0b2dnbGVCb2R5Q2xhc3MoYm9keUNsYXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWJvZHlDbGFzcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBib2R5ID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2JvZHknKVswXTtcbiAgICBjb25zdCBib2R5Q2xhc3NJdGVtcyA9IGJvZHlDbGFzcy5zcGxpdCgnICcpO1xuICAgIGlmICghdGhpcy5tb2RhbHMubGVuZ3RoKSB7XG4gICAgICBib2R5LmNsYXNzTGlzdC5yZW1vdmUoLi4uYm9keUNsYXNzSXRlbXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBib2R5LmNsYXNzTGlzdC5hZGQoLi4uYm9keUNsYXNzSXRlbXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBpZiB0aGUgb3B0aW9uIHRvIGNsb3NlIG9uIGJhY2tncm91bmQgY2xpY2sgaXMgc2V0LCB0aGVuIGhvb2sgdXAgYSBjYWxsYmFja1xuICAgKiBAcGFyYW0gbW9kYWxXcmFwcGVyXG4gICAqL1xuICBwcml2YXRlIGNvbmZpZ3VyZUNsb3NlT25DbGlja091dHNpZGUobW9kYWxXcmFwcGVyOiBTaW1wbGVNb2RhbFdyYXBwZXJDb21wb25lbnQpIHtcbiAgICBtb2RhbFdyYXBwZXIub25DbGlja091dHNpZGVNb2RhbENvbnRlbnQoKCkgPT4ge1xuICAgICAgaWYgKG1vZGFsV3JhcHBlci5jb250ZW50Lm9wdGlvbnMuY2xvc2VPbkNsaWNrT3V0c2lkZSkge1xuICAgICAgICBtb2RhbFdyYXBwZXIuY29udGVudC5jbG9zZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEF1dG8gZm9jdXMgbyB0aGUgZmlyc3QgZWxlbWVudCBpZiBhdXRvZm9jdXMgaXMgb25cbiAgICogQHBhcmFtIGNvbXBvbmVudFdyYXBwZXJcbiAgICogQHBhcmFtIGF1dG9Gb2N1c1xuICAgKi9cbiAgcHJpdmF0ZSBhdXRvRm9jdXNGaXJzdEVsZW1lbnQoY29tcG9uZW50V3JhcHBlcjogRWxlbWVudFJlZiwgYXV0b0ZvY3VzOiBib29sZWFuKSB7XG4gICAgaWYgKGF1dG9Gb2N1cykge1xuICAgICAgY29uc3QgZm9jdXNhYmxlID0gY29tcG9uZW50V3JhcHBlci5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoXG4gICAgICAgICdidXR0b24sIFtocmVmXSwgaW5wdXQsIHNlbGVjdCwgdGV4dGFyZWEsIFt0YWJpbmRleF06bm90KFt0YWJpbmRleD1cIi0xXCJdKScsXG4gICAgICApO1xuICAgICAgaWYgKGZvY3VzYWJsZSAmJiBmb2N1c2FibGUubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMucHJldmlvdXNBY3RpdmVFbGVtZW50ID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgICAgICAgZm9jdXNhYmxlWzBdLmZvY3VzKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc3RvcmVzIHRoZSBsYXN0IGZvY3VzIGlzIHRoZXJlIHdhcyBvbmVcbiAgICovXG4gIHByaXZhdGUgcmVzdG9yZVByZXZpb3VzRm9jdXMoKSB7XG4gICAgaWYgKHRoaXMucHJldmlvdXNBY3RpdmVFbGVtZW50KSB7XG4gICAgICB0aGlzLnByZXZpb3VzQWN0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgICAgdGhpcy5wcmV2aW91c0FjdGl2ZUVsZW1lbnQgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmUgdGhlIGFkZGluZyBhbmQgcmVtb3ZhbCBvZiBhIHdyYXBwZXIgY2xhc3MgLSBwcmVkb21pbmFudGx5IGFuaW1hdGlvbiBmb2N1c2VkXG4gICAqIEBwYXJhbSBtb2RhbFdyYXBwZXJFbFxuICAgKiBAcGFyYW0gd3JhcHBlckNsYXNzXG4gICAqL1xuICBwcml2YXRlIHRvZ2dsZVdyYXBwZXJDbGFzcyhtb2RhbFdyYXBwZXJFbDogRWxlbWVudFJlZiwgd3JhcHBlckNsYXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB3cmFwcGVyQ2xhc3NMaXN0ID0gbW9kYWxXcmFwcGVyRWwubmF0aXZlRWxlbWVudC5jbGFzc0xpc3Q7XG4gICAgY29uc3Qgd3JhcHBlckNsYXNzSXRlbXMgPSB3cmFwcGVyQ2xhc3Muc3BsaXQoJyAnKTtcbiAgICBpZiAod3JhcHBlckNsYXNzTGlzdC50b1N0cmluZygpLmluZGV4T2Yod3JhcHBlckNsYXNzKSAhPT0gLTEpIHtcbiAgICAgIHdyYXBwZXJDbGFzc0xpc3QucmVtb3ZlKC4uLndyYXBwZXJDbGFzc0l0ZW1zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd3JhcHBlckNsYXNzTGlzdC5hZGQoLi4ud3JhcHBlckNsYXNzSXRlbXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIHRoZSBkcmFnIG9wdGlvbiBvbiB0aGUgbW9kYWwgaWYgdGhlIG9wdGlvbnMgaGF2ZSBpdCBlbmFibGVkXG4gICAqIEBwYXJhbSBjb21wb25lbnRcbiAgICogQHBhcmFtIG9wdGlvbnNcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgc2V0RHJhZ2dhYmxlKGNvbXBvbmVudDogQ29tcG9uZW50UmVmPFNpbXBsZU1vZGFsQ29tcG9uZW50PGFueSwgYW55Pj4sIG9wdGlvbnM6IFNpbXBsZU1vZGFsT3B0aW9uc092ZXJyaWRlcyk6IHZvaWQge1xuICAgIGNvbnN0IGRyYWdnYWJsZURpcmVjdGl2ZSA9IG5ldyBEcmFnZ2FibGVEaXJlY3RpdmUoY29tcG9uZW50LmxvY2F0aW9uLCB0aGlzLm5nWm9uZSwgdGhpcy5yZW5kZXJlcik7XG4gICAgZHJhZ2dhYmxlRGlyZWN0aXZlLmRyYWdUYXJnZXQgPSBjb21wb25lbnQubG9jYXRpb24ubmF0aXZlRWxlbWVudDtcbiAgICBkcmFnZ2FibGVEaXJlY3RpdmUuZHJhZ0hhbmRsZSA9IGNvbXBvbmVudC5pbnN0YW5jZS5oYW5kbGUgPyBjb21wb25lbnQuaW5zdGFuY2UuaGFuZGxlLm5hdGl2ZUVsZW1lbnQgOiB1bmRlZmluZWQ7XG4gICAgZHJhZ2dhYmxlRGlyZWN0aXZlLm5nQWZ0ZXJWaWV3SW5pdCgpO1xuICAgIGNvbXBvbmVudC5sb2NhdGlvbi5uYXRpdmVFbGVtZW50LmNsYXNzTGlzdC5hZGQob3B0aW9ucy5kcmFnZ2FibGVDbGFzcyk7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIGZ1bmN0aW9uIGZvciBhIG1vcmUgcmVhZGFibGUgdGltZW91dFxuICAgKiBAcGFyYW0gbXNcbiAgICovXG4gIHByaXZhdGUgd2FpdChtczogbnVtYmVyID0gMCk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx1bmtub3duPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHJlc29sdmUodW5kZWZpbmVkKSwgbXMpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEluc3RydWN0cyB0aGUgaG9sZGVyIHRvIHJlbW92ZSB0aGUgbW9kYWwgYW5kXG4gICAqIHJlbW92ZXMgdGhpcyBjb21wb25lbnQgZnJvbSB0aGUgY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge1NpbXBsZU1vZGFsQ29tcG9uZW50fSBjb21wb25lbnRcbiAgICovXG4gIHByaXZhdGUgcmVtb3ZlTW9kYWxGcm9tQXJyYXkoY29tcG9uZW50KTogdm9pZCB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLm1vZGFscy5pbmRleE9mKGNvbXBvbmVudCk7XG4gICAgaWYgKGluZGV4ID4gLTEpIHtcbiAgICAgIHRoaXMudmlld0NvbnRhaW5lci5yZW1vdmUoaW5kZXgpO1xuICAgICAgdGhpcy5tb2RhbHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==