/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { DOCUMENT } from '@angular/common'; import { ApplicationRef, Inject, Injectable, Injector, NgZone, RendererFactory2, TemplateRef } from '@angular/core'; import { Subject } from 'rxjs'; import { ngbFocusTrap } from '../util/focus-trap'; import { ContentRef } from '../util/popup'; import { ScrollBar } from '../util/scrollbar'; import { isDefined, isString } from '../util/util'; import { NgbModalBackdrop } from './modal-backdrop'; import { NgbActiveModal, NgbModalRef } from './modal-ref'; import { NgbModalWindow } from './modal-window'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "../util/scrollbar"; export class NgbModalStack { /** * @param {?} _applicationRef * @param {?} _injector * @param {?} _document * @param {?} _scrollBar * @param {?} _rendererFactory * @param {?} _ngZone */ constructor(_applicationRef, _injector, _document, _scrollBar, _rendererFactory, _ngZone) { this._applicationRef = _applicationRef; this._injector = _injector; this._document = _document; this._scrollBar = _scrollBar; this._rendererFactory = _rendererFactory; this._ngZone = _ngZone; this._activeWindowCmptHasChanged = new Subject(); this._ariaHiddenValues = new Map(); this._backdropAttributes = ['backdropClass']; this._modalRefs = []; this._windowAttributes = ['ariaLabelledBy', 'backdrop', 'centered', 'keyboard', 'scrollable', 'size', 'windowClass']; this._windowCmpts = []; // Trap focus on active WindowCmpt this._activeWindowCmptHasChanged.subscribe((/** * @return {?} */ () => { if (this._windowCmpts.length) { /** @type {?} */ const activeWindowCmpt = this._windowCmpts[this._windowCmpts.length - 1]; ngbFocusTrap(this._ngZone, activeWindowCmpt.location.nativeElement, this._activeWindowCmptHasChanged); this._revertAriaHidden(); this._setAriaHidden(activeWindowCmpt.location.nativeElement); } })); } /** * @param {?} moduleCFR * @param {?} contentInjector * @param {?} content * @param {?} options * @return {?} */ open(moduleCFR, contentInjector, content, options) { /** @type {?} */ const containerEl = isDefined(options.container) ? this._document.querySelector(options.container) : this._document.body; /** @type {?} */ const renderer = this._rendererFactory.createRenderer(null, null); /** @type {?} */ const revertPaddingForScrollBar = this._scrollBar.compensate(); /** @type {?} */ const removeBodyClass = (/** * @return {?} */ () => { if (!this._modalRefs.length) { renderer.removeClass(this._document.body, 'modal-open'); this._revertAriaHidden(); } }); if (!containerEl) { throw new Error(`The specified modal container "${options.container || 'body'}" was not found in the DOM.`); } /** @type {?} */ const activeModal = new NgbActiveModal(); /** @type {?} */ const contentRef = this._getContentRef(moduleCFR, options.injector || contentInjector, content, activeModal, options); /** @type {?} */ let backdropCmptRef = options.backdrop !== false ? this._attachBackdrop(moduleCFR, containerEl) : null; /** @type {?} */ let windowCmptRef = this._attachWindowComponent(moduleCFR, containerEl, contentRef); /** @type {?} */ let ngbModalRef = new NgbModalRef(windowCmptRef, contentRef, backdropCmptRef, options.beforeDismiss); this._registerModalRef(ngbModalRef); this._registerWindowCmpt(windowCmptRef); ngbModalRef.result.then(revertPaddingForScrollBar, revertPaddingForScrollBar); ngbModalRef.result.then(removeBodyClass, removeBodyClass); activeModal.close = (/** * @param {?} result * @return {?} */ (result) => { ngbModalRef.close(result); }); activeModal.dismiss = (/** * @param {?} reason * @return {?} */ (reason) => { ngbModalRef.dismiss(reason); }); this._applyWindowOptions(windowCmptRef.instance, options); if (this._modalRefs.length === 1) { renderer.addClass(this._document.body, 'modal-open'); } if (backdropCmptRef && backdropCmptRef.instance) { this._applyBackdropOptions(backdropCmptRef.instance, options); } return ngbModalRef; } /** * @param {?=} reason * @return {?} */ dismissAll(reason) { this._modalRefs.forEach((/** * @param {?} ngbModalRef * @return {?} */ ngbModalRef => ngbModalRef.dismiss(reason))); } /** * @return {?} */ hasOpenModals() { return this._modalRefs.length > 0; } /** * @private * @param {?} moduleCFR * @param {?} containerEl * @return {?} */ _attachBackdrop(moduleCFR, containerEl) { /** @type {?} */ let backdropFactory = moduleCFR.resolveComponentFactory(NgbModalBackdrop); /** @type {?} */ let backdropCmptRef = backdropFactory.create(this._injector); this._applicationRef.attachView(backdropCmptRef.hostView); containerEl.appendChild(backdropCmptRef.location.nativeElement); return backdropCmptRef; } /** * @private * @param {?} moduleCFR * @param {?} containerEl * @param {?} contentRef * @return {?} */ _attachWindowComponent(moduleCFR, containerEl, contentRef) { /** @type {?} */ let windowFactory = moduleCFR.resolveComponentFactory(NgbModalWindow); /** @type {?} */ let windowCmptRef = windowFactory.create(this._injector, contentRef.nodes); this._applicationRef.attachView(windowCmptRef.hostView); containerEl.appendChild(windowCmptRef.location.nativeElement); return windowCmptRef; } /** * @private * @param {?} windowInstance * @param {?} options * @return {?} */ _applyWindowOptions(windowInstance, options) { this._windowAttributes.forEach((/** * @param {?} optionName * @return {?} */ (optionName) => { if (isDefined(options[optionName])) { windowInstance[optionName] = options[optionName]; } })); } /** * @private * @param {?} backdropInstance * @param {?} options * @return {?} */ _applyBackdropOptions(backdropInstance, options) { this._backdropAttributes.forEach((/** * @param {?} optionName * @return {?} */ (optionName) => { if (isDefined(options[optionName])) { backdropInstance[optionName] = options[optionName]; } })); } /** * @private * @param {?} moduleCFR * @param {?} contentInjector * @param {?} content * @param {?} activeModal * @param {?} options * @return {?} */ _getContentRef(moduleCFR, contentInjector, content, activeModal, options) { if (!content) { return new ContentRef([]); } else if (content instanceof TemplateRef) { return this._createFromTemplateRef(content, activeModal); } else if (isString(content)) { return this._createFromString(content); } else { return this._createFromComponent(moduleCFR, contentInjector, content, activeModal, options); } } /** * @private * @param {?} content * @param {?} activeModal * @return {?} */ _createFromTemplateRef(content, activeModal) { /** @type {?} */ const context = { $implicit: activeModal, /** * @param {?} result * @return {?} */ close(result) { activeModal.close(result); }, /** * @param {?} reason * @return {?} */ dismiss(reason) { activeModal.dismiss(reason); } }; /** @type {?} */ const viewRef = content.createEmbeddedView(context); this._applicationRef.attachView(viewRef); return new ContentRef([viewRef.rootNodes], viewRef); } /** * @private * @param {?} content * @return {?} */ _createFromString(content) { /** @type {?} */ const component = this._document.createTextNode(`${content}`); return new ContentRef([[component]]); } /** * @private * @param {?} moduleCFR * @param {?} contentInjector * @param {?} content * @param {?} context * @param {?} options * @return {?} */ _createFromComponent(moduleCFR, contentInjector, content, context, options) { /** @type {?} */ const contentCmptFactory = moduleCFR.resolveComponentFactory(content); /** @type {?} */ const modalContentInjector = Injector.create({ providers: [{ provide: NgbActiveModal, useValue: context }], parent: contentInjector }); /** @type {?} */ const componentRef = contentCmptFactory.create(modalContentInjector); /** @type {?} */ const componentNativeEl = componentRef.location.nativeElement; if (options.scrollable) { ((/** @type {?} */ (componentNativeEl))).classList.add('component-host-scrollable'); } this._applicationRef.attachView(componentRef.hostView); // FIXME: we should here get rid of the component nativeElement // and use `[Array.from(componentNativeEl.childNodes)]` instead and remove the above CSS class. return new ContentRef([[componentNativeEl]], componentRef.hostView, componentRef); } /** * @private * @param {?} element * @return {?} */ _setAriaHidden(element) { /** @type {?} */ const parent = element.parentElement; if (parent && element !== this._document.body) { Array.from(parent.children).forEach((/** * @param {?} sibling * @return {?} */ sibling => { if (sibling !== element && sibling.nodeName !== 'SCRIPT') { this._ariaHiddenValues.set(sibling, sibling.getAttribute('aria-hidden')); sibling.setAttribute('aria-hidden', 'true'); } })); this._setAriaHidden(parent); } } /** * @private * @return {?} */ _revertAriaHidden() { this._ariaHiddenValues.forEach((/** * @param {?} value * @param {?} element * @return {?} */ (value, element) => { if (value) { element.setAttribute('aria-hidden', value); } else { element.removeAttribute('aria-hidden'); } })); this._ariaHiddenValues.clear(); } /** * @private * @param {?} ngbModalRef * @return {?} */ _registerModalRef(ngbModalRef) { /** @type {?} */ const unregisterModalRef = (/** * @return {?} */ () => { /** @type {?} */ const index = this._modalRefs.indexOf(ngbModalRef); if (index > -1) { this._modalRefs.splice(index, 1); } }); this._modalRefs.push(ngbModalRef); ngbModalRef.result.then(unregisterModalRef, unregisterModalRef); } /** * @private * @param {?} ngbWindowCmpt * @return {?} */ _registerWindowCmpt(ngbWindowCmpt) { this._windowCmpts.push(ngbWindowCmpt); this._activeWindowCmptHasChanged.next(); ngbWindowCmpt.onDestroy((/** * @return {?} */ () => { /** @type {?} */ const index = this._windowCmpts.indexOf(ngbWindowCmpt); if (index > -1) { this._windowCmpts.splice(index, 1); this._activeWindowCmptHasChanged.next(); } })); } } NgbModalStack.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ NgbModalStack.ctorParameters = () => [ { type: ApplicationRef }, { type: Injector }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }, { type: ScrollBar }, { type: RendererFactory2 }, { type: NgZone } ]; /** @nocollapse */ NgbModalStack.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: function NgbModalStack_Factory() { return new NgbModalStack(i0.ɵɵinject(i0.ApplicationRef), i0.ɵɵinject(i0.INJECTOR), i0.ɵɵinject(i1.DOCUMENT), i0.ɵɵinject(i2.ScrollBar), i0.ɵɵinject(i0.RendererFactory2), i0.ɵɵinject(i0.NgZone)); }, token: NgbModalStack, providedIn: "root" }); if (false) { /** * @type {?} * @private */ NgbModalStack.prototype._activeWindowCmptHasChanged; /** * @type {?} * @private */ NgbModalStack.prototype._ariaHiddenValues; /** * @type {?} * @private */ NgbModalStack.prototype._backdropAttributes; /** * @type {?} * @private */ NgbModalStack.prototype._modalRefs; /** * @type {?} * @private */ NgbModalStack.prototype._windowAttributes; /** * @type {?} * @private */ NgbModalStack.prototype._windowCmpts; /** * @type {?} * @private */ NgbModalStack.prototype._applicationRef; /** * @type {?} * @private */ NgbModalStack.prototype._injector; /** * @type {?} * @private */ NgbModalStack.prototype._document; /** * @type {?} * @private */ NgbModalStack.prototype._scrollBar; /** * @type {?} * @private */ NgbModalStack.prototype._rendererFactory; /** * @type {?} * @private */ NgbModalStack.prototype._ngZone; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwtc3RhY2suanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AbmctYm9vdHN0cmFwL25nLWJvb3RzdHJhcC8iLCJzb3VyY2VzIjpbIm1vZGFsL21vZGFsLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDekMsT0FBTyxFQUNMLGNBQWMsRUFHZCxNQUFNLEVBQ04sVUFBVSxFQUNWLFFBQVEsRUFDUixNQUFNLEVBQ04sZ0JBQWdCLEVBQ2hCLFdBQVcsRUFDWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBRTdCLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUM1QyxPQUFPLEVBQUMsU0FBUyxFQUFFLFFBQVEsRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUNqRCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUVsRCxPQUFPLEVBQUMsY0FBYyxFQUFFLFdBQVcsRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUN4RCxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7Ozs7QUFHOUMsTUFBTSxPQUFPLGFBQWE7Ozs7Ozs7OztJQVN4QixZQUNZLGVBQStCLEVBQVUsU0FBbUIsRUFBNEIsU0FBYyxFQUN0RyxVQUFxQixFQUFVLGdCQUFrQyxFQUFVLE9BQWU7UUFEMUYsb0JBQWUsR0FBZixlQUFlLENBQWdCO1FBQVUsY0FBUyxHQUFULFNBQVMsQ0FBVTtRQUE0QixjQUFTLEdBQVQsU0FBUyxDQUFLO1FBQ3RHLGVBQVUsR0FBVixVQUFVLENBQVc7UUFBVSxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQVUsWUFB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Ozs7OztJQUNwRCwwQ0FBNEQ7Ozs7O0lBQzVELDRDQUFnRDs7Ozs7SUFDaEQsbUNBQXVDOzs7OztJQUN2QywwQ0FDZ0c7Ozs7O0lBQ2hHLHFDQUEwRDs7Ozs7SUFHdEQsd0NBQXVDOzs7OztJQUFFLGtDQUEyQjs7Ozs7SUFBRSxrQ0FBd0M7Ozs7O0lBQzlHLG1DQUE2Qjs7Ozs7SUFBRSx5Q0FBMEM7Ozs7O0lBQUUsZ0NBQXVCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtET0NVTUVOVH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gIEFwcGxpY2F0aW9uUmVmLFxuICBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gIENvbXBvbmVudFJlZixcbiAgSW5qZWN0LFxuICBJbmplY3RhYmxlLFxuICBJbmplY3RvcixcbiAgTmdab25lLFxuICBSZW5kZXJlckZhY3RvcnkyLFxuICBUZW1wbGF0ZVJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7U3ViamVjdH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7bmdiRm9jdXNUcmFwfSBmcm9tICcuLi91dGlsL2ZvY3VzLXRyYXAnO1xuaW1wb3J0IHtDb250ZW50UmVmfSBmcm9tICcuLi91dGlsL3BvcHVwJztcbmltcG9ydCB7U2Nyb2xsQmFyfSBmcm9tICcuLi91dGlsL3Njcm9sbGJhcic7XG5pbXBvcnQge2lzRGVmaW5lZCwgaXNTdHJpbmd9IGZyb20gJy4uL3V0aWwvdXRpbCc7XG5pbXBvcnQge05nYk1vZGFsQmFja2Ryb3B9IGZyb20gJy4vbW9kYWwtYmFja2Ryb3AnO1xuaW1wb3J0IHtOZ2JNb2RhbE9wdGlvbnN9IGZyb20gJy4vbW9kYWwtY29uZmlnJztcbmltcG9ydCB7TmdiQWN0aXZlTW9kYWwsIE5nYk1vZGFsUmVmfSBmcm9tICcuL21vZGFsLXJlZic7XG5pbXBvcnQge05nYk1vZGFsV2luZG93fSBmcm9tICcuL21vZGFsLXdpbmRvdyc7XG5cbkBJbmplY3RhYmxlKHtwcm92aWRlZEluOiAncm9vdCd9KVxuZXhwb3J0IGNsYXNzIE5nYk1vZGFsU3RhY2sge1xuICBwcml2YXRlIF9hY3RpdmVXaW5kb3dDbXB0SGFzQ2hhbmdlZCA9IG5ldyBTdWJqZWN0KCk7XG4gIHByaXZhdGUgX2FyaWFIaWRkZW5WYWx1ZXM6IE1hcDxFbGVtZW50LCBzdHJpbmc+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIF9iYWNrZHJvcEF0dHJpYnV0ZXMgPSBbJ2JhY2tkcm9wQ2xhc3MnXTtcbiAgcHJpdmF0ZSBfbW9kYWxSZWZzOiBOZ2JNb2RhbFJlZltdID0gW107XG4gIHByaXZhdGUgX3dpbmRvd0F0dHJpYnV0ZXMgPVxuICAgICAgWydhcmlhTGFiZWxsZWRCeScsICdiYWNrZHJvcCcsICdjZW50ZXJlZCcsICdrZXlib2FyZCcsICdzY3JvbGxhYmxlJywgJ3NpemUnLCAnd2luZG93Q2xhc3MnXTtcbiAgcHJpdmF0ZSBfd2luZG93Q21wdHM6IENvbXBvbmVudFJlZjxOZ2JNb2RhbFdpbmRvdz5bXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHJpdmF0ZSBfYXBwbGljYXRpb25SZWY6IEFwcGxpY2F0aW9uUmVmLCBwcml2YXRlIF9pbmplY3RvcjogSW5qZWN0b3IsIEBJbmplY3QoRE9DVU1FTlQpIHByaXZhdGUgX2RvY3VtZW50OiBhbnksXG4gICAgICBwcml2YXRlIF9zY3JvbGxCYXI6IFNjcm9sbEJhciwgcHJpdmF0ZSBfcmVuZGVyZXJGYWN0b3J5OiBSZW5kZXJlckZhY3RvcnkyLCBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZSkge1xuICAgIC8vIFRyYXAgZm9jdXMgb24gYWN0aXZlIFdpbmRvd0NtcHRcbiAgICB0aGlzLl9hY3RpdmVXaW5kb3dDbXB0SGFzQ2hhbmdlZC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX3dpbmRvd0NtcHRzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCBhY3RpdmVXaW5kb3dDbXB0ID0gdGhpcy5fd2luZG93Q21wdHNbdGhpcy5fd2luZG93Q21wdHMubGVuZ3RoIC0gMV07XG4gICAgICAgIG5nYkZvY3VzVHJhcCh0aGlzLl9uZ1pvbmUsIGFjdGl2ZVdpbmRvd0NtcHQubG9jYXRpb24ubmF0aXZlRWxlbWVudCwgdGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWQpO1xuICAgICAgICB0aGlzLl9yZXZlcnRBcmlhSGlkZGVuKCk7XG4gICAgICAgIHRoaXMuX3NldEFyaWFIaWRkZW4oYWN0aXZlV2luZG93Q21wdC5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIG9wZW4obW9kdWxlQ0ZSOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsIGNvbnRlbnRJbmplY3RvcjogSW5qZWN0b3IsIGNvbnRlbnQ6IGFueSwgb3B0aW9ucyk6IE5nYk1vZGFsUmVmIHtcbiAgICBjb25zdCBjb250YWluZXJFbCA9XG4gICAgICAgIGlzRGVmaW5lZChvcHRpb25zLmNvbnRhaW5lcikgPyB0aGlzLl9kb2N1bWVudC5xdWVyeVNlbGVjdG9yKG9wdGlvbnMuY29udGFpbmVyKSA6IHRoaXMuX2RvY3VtZW50LmJvZHk7XG4gICAgY29uc3QgcmVuZGVyZXIgPSB0aGlzLl9yZW5kZXJlckZhY3RvcnkuY3JlYXRlUmVuZGVyZXIobnVsbCwgbnVsbCk7XG5cbiAgICBjb25zdCByZXZlcnRQYWRkaW5nRm9yU2Nyb2xsQmFyID0gdGhpcy5fc2Nyb2xsQmFyLmNvbXBlbnNhdGUoKTtcbiAgICBjb25zdCByZW1vdmVCb2R5Q2xhc3MgPSAoKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuX21vZGFsUmVmcy5sZW5ndGgpIHtcbiAgICAgICAgcmVuZGVyZXIucmVtb3ZlQ2xhc3ModGhpcy5fZG9jdW1lbnQuYm9keSwgJ21vZGFsLW9wZW4nKTtcbiAgICAgICAgdGhpcy5fcmV2ZXJ0QXJpYUhpZGRlbigpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoIWNvbnRhaW5lckVsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBzcGVjaWZpZWQgbW9kYWwgY29udGFpbmVyIFwiJHtvcHRpb25zLmNvbnRhaW5lciB8fCAnYm9keSd9XCIgd2FzIG5vdCBmb3VuZCBpbiB0aGUgRE9NLmApO1xuICAgIH1cblxuICAgIGNvbnN0IGFjdGl2ZU1vZGFsID0gbmV3IE5nYkFjdGl2ZU1vZGFsKCk7XG4gICAgY29uc3QgY29udGVudFJlZiA9XG4gICAgICAgIHRoaXMuX2dldENvbnRlbnRSZWYobW9kdWxlQ0ZSLCBvcHRpb25zLmluamVjdG9yIHx8IGNvbnRlbnRJbmplY3RvciwgY29udGVudCwgYWN0aXZlTW9kYWwsIG9wdGlvbnMpO1xuXG4gICAgbGV0IGJhY2tkcm9wQ21wdFJlZjogQ29tcG9uZW50UmVmPE5nYk1vZGFsQmFja2Ryb3A+ID1cbiAgICAgICAgb3B0aW9ucy5iYWNrZHJvcCAhPT0gZmFsc2UgPyB0aGlzLl9hdHRhY2hCYWNrZHJvcChtb2R1bGVDRlIsIGNvbnRhaW5lckVsKSA6IG51bGw7XG4gICAgbGV0IHdpbmRvd0NtcHRSZWY6IENvbXBvbmVudFJlZjxOZ2JNb2RhbFdpbmRvdz4gPSB0aGlzLl9hdHRhY2hXaW5kb3dDb21wb25lbnQobW9kdWxlQ0ZSLCBjb250YWluZXJFbCwgY29udGVudFJlZik7XG4gICAgbGV0IG5nYk1vZGFsUmVmOiBOZ2JNb2RhbFJlZiA9IG5ldyBOZ2JNb2RhbFJlZih3aW5kb3dDbXB0UmVmLCBjb250ZW50UmVmLCBiYWNrZHJvcENtcHRSZWYsIG9wdGlvbnMuYmVmb3JlRGlzbWlzcyk7XG5cbiAgICB0aGlzLl9yZWdpc3Rlck1vZGFsUmVmKG5nYk1vZGFsUmVmKTtcbiAgICB0aGlzLl9yZWdpc3RlcldpbmRvd0NtcHQod2luZG93Q21wdFJlZik7XG4gICAgbmdiTW9kYWxSZWYucmVzdWx0LnRoZW4ocmV2ZXJ0UGFkZGluZ0ZvclNjcm9sbEJhciwgcmV2ZXJ0UGFkZGluZ0ZvclNjcm9sbEJhcik7XG4gICAgbmdiTW9kYWxSZWYucmVzdWx0LnRoZW4ocmVtb3ZlQm9keUNsYXNzLCByZW1vdmVCb2R5Q2xhc3MpO1xuICAgIGFjdGl2ZU1vZGFsLmNsb3NlID0gKHJlc3VsdDogYW55KSA9PiB7IG5nYk1vZGFsUmVmLmNsb3NlKHJlc3VsdCk7IH07XG4gICAgYWN0aXZlTW9kYWwuZGlzbWlzcyA9IChyZWFzb246IGFueSkgPT4geyBuZ2JNb2RhbFJlZi5kaXNtaXNzKHJlYXNvbik7IH07XG5cbiAgICB0aGlzLl9hcHBseVdpbmRvd09wdGlvbnMod2luZG93Q21wdFJlZi5pbnN0YW5jZSwgb3B0aW9ucyk7XG4gICAgaWYgKHRoaXMuX21vZGFsUmVmcy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJlbmRlcmVyLmFkZENsYXNzKHRoaXMuX2RvY3VtZW50LmJvZHksICdtb2RhbC1vcGVuJyk7XG4gICAgfVxuXG4gICAgaWYgKGJhY2tkcm9wQ21wdFJlZiAmJiBiYWNrZHJvcENtcHRSZWYuaW5zdGFuY2UpIHtcbiAgICAgIHRoaXMuX2FwcGx5QmFja2Ryb3BPcHRpb25zKGJhY2tkcm9wQ21wdFJlZi5pbnN0YW5jZSwgb3B0aW9ucyk7XG4gICAgfVxuICAgIHJldHVybiBuZ2JNb2RhbFJlZjtcbiAgfVxuXG4gIGRpc21pc3NBbGwocmVhc29uPzogYW55KSB7IHRoaXMuX21vZGFsUmVmcy5mb3JFYWNoKG5nYk1vZGFsUmVmID0+IG5nYk1vZGFsUmVmLmRpc21pc3MocmVhc29uKSk7IH1cblxuICBoYXNPcGVuTW9kYWxzKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5fbW9kYWxSZWZzLmxlbmd0aCA+IDA7IH1cblxuICBwcml2YXRlIF9hdHRhY2hCYWNrZHJvcChtb2R1bGVDRlI6IENvbXBvbmVudEZhY3RvcnlSZXNvbHZlciwgY29udGFpbmVyRWw6IGFueSk6IENvbXBvbmVudFJlZjxOZ2JNb2RhbEJhY2tkcm9wPiB7XG4gICAgbGV0IGJhY2tkcm9wRmFjdG9yeSA9IG1vZHVsZUNGUi5yZXNvbHZlQ29tcG9uZW50RmFjdG9yeShOZ2JNb2RhbEJhY2tkcm9wKTtcbiAgICBsZXQgYmFja2Ryb3BDbXB0UmVmID0gYmFja2Ryb3BGYWN0b3J5LmNyZWF0ZSh0aGlzLl9pbmplY3Rvcik7XG4gICAgdGhpcy5fYXBwbGljYXRpb25SZWYuYXR0YWNoVmlldyhiYWNrZHJvcENtcHRSZWYuaG9zdFZpZXcpO1xuICAgIGNvbnRhaW5lckVsLmFwcGVuZENoaWxkKGJhY2tkcm9wQ21wdFJlZi5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcbiAgICByZXR1cm4gYmFja2Ryb3BDbXB0UmVmO1xuICB9XG5cbiAgcHJpdmF0ZSBfYXR0YWNoV2luZG93Q29tcG9uZW50KG1vZHVsZUNGUjogQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLCBjb250YWluZXJFbDogYW55LCBjb250ZW50UmVmOiBhbnkpOlxuICAgICAgQ29tcG9uZW50UmVmPE5nYk1vZGFsV2luZG93PiB7XG4gICAgbGV0IHdpbmRvd0ZhY3RvcnkgPSBtb2R1bGVDRlIucmVzb2x2ZUNvbXBvbmVudEZhY3RvcnkoTmdiTW9kYWxXaW5kb3cpO1xuICAgIGxldCB3aW5kb3dDbXB0UmVmID0gd2luZG93RmFjdG9yeS5jcmVhdGUodGhpcy5faW5qZWN0b3IsIGNvbnRlbnRSZWYubm9kZXMpO1xuICAgIHRoaXMuX2FwcGxpY2F0aW9uUmVmLmF0dGFjaFZpZXcod2luZG93Q21wdFJlZi5ob3N0Vmlldyk7XG4gICAgY29udGFpbmVyRWwuYXBwZW5kQ2hpbGQod2luZG93Q21wdFJlZi5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcbiAgICByZXR1cm4gd2luZG93Q21wdFJlZjtcbiAgfVxuXG4gIHByaXZhdGUgX2FwcGx5V2luZG93T3B0aW9ucyh3aW5kb3dJbnN0YW5jZTogTmdiTW9kYWxXaW5kb3csIG9wdGlvbnM6IE9iamVjdCk6IHZvaWQge1xuICAgIHRoaXMuX3dpbmRvd0F0dHJpYnV0ZXMuZm9yRWFjaCgob3B0aW9uTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoaXNEZWZpbmVkKG9wdGlvbnNbb3B0aW9uTmFtZV0pKSB7XG4gICAgICAgIHdpbmRvd0luc3RhbmNlW29wdGlvbk5hbWVdID0gb3B0aW9uc1tvcHRpb25OYW1lXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2FwcGx5QmFja2Ryb3BPcHRpb25zKGJhY2tkcm9wSW5zdGFuY2U6IE5nYk1vZGFsQmFja2Ryb3AsIG9wdGlvbnM6IE9iamVjdCk6IHZvaWQge1xuICAgIHRoaXMuX2JhY2tkcm9wQXR0cmlidXRlcy5mb3JFYWNoKChvcHRpb25OYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmIChpc0RlZmluZWQob3B0aW9uc1tvcHRpb25OYW1lXSkpIHtcbiAgICAgICAgYmFja2Ryb3BJbnN0YW5jZVtvcHRpb25OYW1lXSA9IG9wdGlvbnNbb3B0aW9uTmFtZV07XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9nZXRDb250ZW50UmVmKFxuICAgICAgbW9kdWxlQ0ZSOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsIGNvbnRlbnRJbmplY3RvcjogSW5qZWN0b3IsIGNvbnRlbnQ6IGFueSwgYWN0aXZlTW9kYWw6IE5nYkFjdGl2ZU1vZGFsLFxuICAgICAgb3B0aW9uczogTmdiTW9kYWxPcHRpb25zKTogQ29udGVudFJlZiB7XG4gICAgaWYgKCFjb250ZW50KSB7XG4gICAgICByZXR1cm4gbmV3IENvbnRlbnRSZWYoW10pO1xuICAgIH0gZWxzZSBpZiAoY29udGVudCBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY3JlYXRlRnJvbVRlbXBsYXRlUmVmKGNvbnRlbnQsIGFjdGl2ZU1vZGFsKTtcbiAgICB9IGVsc2UgaWYgKGlzU3RyaW5nKGNvbnRlbnQpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY3JlYXRlRnJvbVN0cmluZyhjb250ZW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX2NyZWF0ZUZyb21Db21wb25lbnQobW9kdWxlQ0ZSLCBjb250ZW50SW5qZWN0b3IsIGNvbnRlbnQsIGFjdGl2ZU1vZGFsLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9jcmVhdGVGcm9tVGVtcGxhdGVSZWYoY29udGVudDogVGVtcGxhdGVSZWY8YW55PiwgYWN0aXZlTW9kYWw6IE5nYkFjdGl2ZU1vZGFsKTogQ29udGVudFJlZiB7XG4gICAgY29uc3QgY29udGV4dCA9IHtcbiAgICAgICRpbXBsaWNpdDogYWN0aXZlTW9kYWwsXG4gICAgICBjbG9zZShyZXN1bHQpIHsgYWN0aXZlTW9kYWwuY2xvc2UocmVzdWx0KTsgfSxcbiAgICAgIGRpc21pc3MocmVhc29uKSB7IGFjdGl2ZU1vZGFsLmRpc21pc3MocmVhc29uKTsgfVxuICAgIH07XG4gICAgY29uc3Qgdmlld1JlZiA9IGNvbnRlbnQuY3JlYXRlRW1iZWRkZWRWaWV3KGNvbnRleHQpO1xuICAgIHRoaXMuX2FwcGxpY2F0aW9uUmVmLmF0dGFjaFZpZXcodmlld1JlZik7XG4gICAgcmV0dXJuIG5ldyBDb250ZW50UmVmKFt2aWV3UmVmLnJvb3ROb2Rlc10sIHZpZXdSZWYpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY3JlYXRlRnJvbVN0cmluZyhjb250ZW50OiBzdHJpbmcpOiBDb250ZW50UmVmIHtcbiAgICBjb25zdCBjb21wb25lbnQgPSB0aGlzLl9kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShgJHtjb250ZW50fWApO1xuICAgIHJldHVybiBuZXcgQ29udGVudFJlZihbW2NvbXBvbmVudF1dKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NyZWF0ZUZyb21Db21wb25lbnQoXG4gICAgICBtb2R1bGVDRlI6IENvbXBvbmVudEZhY3RvcnlSZXNvbHZlciwgY29udGVudEluamVjdG9yOiBJbmplY3RvciwgY29udGVudDogYW55LCBjb250ZXh0OiBOZ2JBY3RpdmVNb2RhbCxcbiAgICAgIG9wdGlvbnM6IE5nYk1vZGFsT3B0aW9ucyk6IENvbnRlbnRSZWYge1xuICAgIGNvbnN0IGNvbnRlbnRDbXB0RmFjdG9yeSA9IG1vZHVsZUNGUi5yZXNvbHZlQ29tcG9uZW50RmFjdG9yeShjb250ZW50KTtcbiAgICBjb25zdCBtb2RhbENvbnRlbnRJbmplY3RvciA9XG4gICAgICAgIEluamVjdG9yLmNyZWF0ZSh7cHJvdmlkZXJzOiBbe3Byb3ZpZGU6IE5nYkFjdGl2ZU1vZGFsLCB1c2VWYWx1ZTogY29udGV4dH1dLCBwYXJlbnQ6IGNvbnRlbnRJbmplY3Rvcn0pO1xuICAgIGNvbnN0IGNvbXBvbmVudFJlZiA9IGNvbnRlbnRDbXB0RmFjdG9yeS5jcmVhdGUobW9kYWxDb250ZW50SW5qZWN0b3IpO1xuICAgIGNvbnN0IGNvbXBvbmVudE5hdGl2ZUVsID0gY29tcG9uZW50UmVmLmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKG9wdGlvbnMuc2Nyb2xsYWJsZSkge1xuICAgICAgKGNvbXBvbmVudE5hdGl2ZUVsIGFzIEhUTUxFbGVtZW50KS5jbGFzc0xpc3QuYWRkKCdjb21wb25lbnQtaG9zdC1zY3JvbGxhYmxlJyk7XG4gICAgfVxuICAgIHRoaXMuX2FwcGxpY2F0aW9uUmVmLmF0dGFjaFZpZXcoY29tcG9uZW50UmVmLmhvc3RWaWV3KTtcbiAgICAvLyBGSVhNRTogd2Ugc2hvdWxkIGhlcmUgZ2V0IHJpZCBvZiB0aGUgY29tcG9uZW50IG5hdGl2ZUVsZW1lbnRcbiAgICAvLyBhbmQgdXNlIGBbQXJyYXkuZnJvbShjb21wb25lbnROYXRpdmVFbC5jaGlsZE5vZGVzKV1gIGluc3RlYWQgYW5kIHJlbW92ZSB0aGUgYWJvdmUgQ1NTIGNsYXNzLlxuICAgIHJldHVybiBuZXcgQ29udGVudFJlZihbW2NvbXBvbmVudE5hdGl2ZUVsXV0sIGNvbXBvbmVudFJlZi5ob3N0VmlldywgY29tcG9uZW50UmVmKTtcbiAgfVxuXG4gIHByaXZhdGUgX3NldEFyaWFIaWRkZW4oZWxlbWVudDogRWxlbWVudCkge1xuICAgIGNvbnN0IHBhcmVudCA9IGVsZW1lbnQucGFyZW50RWxlbWVudDtcbiAgICBpZiAocGFyZW50ICYmIGVsZW1lbnQgIT09IHRoaXMuX2RvY3VtZW50LmJvZHkpIHtcbiAgICAgIEFycmF5LmZyb20ocGFyZW50LmNoaWxkcmVuKS5mb3JFYWNoKHNpYmxpbmcgPT4ge1xuICAgICAgICBpZiAoc2libGluZyAhPT0gZWxlbWVudCAmJiBzaWJsaW5nLm5vZGVOYW1lICE9PSAnU0NSSVBUJykge1xuICAgICAgICAgIHRoaXMuX2FyaWFIaWRkZW5WYWx1ZXMuc2V0KHNpYmxpbmcsIHNpYmxpbmcuZ2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicpKTtcbiAgICAgICAgICBzaWJsaW5nLnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCAndHJ1ZScpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fc2V0QXJpYUhpZGRlbihwYXJlbnQpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3JldmVydEFyaWFIaWRkZW4oKSB7XG4gICAgdGhpcy5fYXJpYUhpZGRlblZhbHVlcy5mb3JFYWNoKCh2YWx1ZSwgZWxlbWVudCkgPT4ge1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsIHZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWhpZGRlbicpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMuX2FyaWFIaWRkZW5WYWx1ZXMuY2xlYXIoKTtcbiAgfVxuXG4gIHByaXZhdGUgX3JlZ2lzdGVyTW9kYWxSZWYobmdiTW9kYWxSZWY6IE5nYk1vZGFsUmVmKSB7XG4gICAgY29uc3QgdW5yZWdpc3Rlck1vZGFsUmVmID0gKCkgPT4ge1xuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLl9tb2RhbFJlZnMuaW5kZXhPZihuZ2JNb2RhbFJlZik7XG4gICAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICB0aGlzLl9tb2RhbFJlZnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHRoaXMuX21vZGFsUmVmcy5wdXNoKG5nYk1vZGFsUmVmKTtcbiAgICBuZ2JNb2RhbFJlZi5yZXN1bHQudGhlbih1bnJlZ2lzdGVyTW9kYWxSZWYsIHVucmVnaXN0ZXJNb2RhbFJlZik7XG4gIH1cblxuICBwcml2YXRlIF9yZWdpc3RlcldpbmRvd0NtcHQobmdiV2luZG93Q21wdDogQ29tcG9uZW50UmVmPE5nYk1vZGFsV2luZG93Pikge1xuICAgIHRoaXMuX3dpbmRvd0NtcHRzLnB1c2gobmdiV2luZG93Q21wdCk7XG4gICAgdGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWQubmV4dCgpO1xuXG4gICAgbmdiV2luZG93Q21wdC5vbkRlc3Ryb3koKCkgPT4ge1xuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLl93aW5kb3dDbXB0cy5pbmRleE9mKG5nYldpbmRvd0NtcHQpO1xuICAgICAgaWYgKGluZGV4ID4gLTEpIHtcbiAgICAgICAgdGhpcy5fd2luZG93Q21wdHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgdGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWQubmV4dCgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG4iXX0=