ornamentum
Version:
Angular Toolkit
240 lines • 24 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { take } from 'rxjs/operators';
/**
* Popover dynamic component loader; Responsible of dynamically rendering angular components to show popover layout.
* @template T
*/
export class PopoverComponentLoader {
/**
* @param {?} componentFactoryResolver
* @param {?} appRef
* @param {?} globalRefService
* @param {?} renderer
* @param {?} resizeService
*/
constructor(componentFactoryResolver, appRef, globalRefService, renderer, resizeService) {
this.componentFactoryResolver = componentFactoryResolver;
this.appRef = appRef;
this.globalRefService = globalRefService;
this.renderer = renderer;
this.resizeService = resizeService;
this.isVisible = false;
}
/**
* Register close on click outside event; Hide event is triggered only if click target is not included in
* exclusion elements collection.
* @private
* @param {...?} exclude - Exclude DOM element reference collection.
* @return {?}
*/
registerClickOutside(...exclude) {
/** @type {?} */
const trackOutsideClick = (/**
* @param {?} event
* @return {?}
*/
(event) => {
if (!exclude.some((/**
* @param {?} el
* @return {?}
*/
el => {
return el.contains((/** @type {?} */ (event.target)));
}))) {
this.hide();
}
});
this.clickListener = this.renderer.listen('document', 'click', trackOutsideClick);
this.touchStartListener = this.renderer.listen('document', 'touchstart', trackOutsideClick);
}
/**
* Set dynamic popover position relative to parent.
* @private
* @param {?} parentElement Parent element reference.
* @param {?} options Component loader options.
* @return {?}
*/
setPosition(parentElement, options) {
/** @type {?} */
const holderElement = options.relativeParentElement || parentElement;
/** @type {?} */
const bodyClientRect = holderElement.getBoundingClientRect();
/** @type {?} */
const elementClientRect = parentElement.getBoundingClientRect();
/** @type {?} */
let left = 0;
/** @type {?} */
let top = 0;
if (options.position.includes('right')) {
left = parentElement.offsetWidth;
}
if (options.position.includes('bottom')) {
top = parentElement.offsetHeight;
}
/** @type {?} */
const componentElement = (/** @type {?} */ (this.componentReference.location.nativeElement));
componentElement.style.top = `${elementClientRect.top - bodyClientRect.top + top + options.floatTop}px`;
componentElement.style.left = `${elementClientRect.left - bodyClientRect.left + left + options.floatLeft}px`;
componentElement.style.position = 'absolute';
componentElement.style.display = 'block';
/** @type {?} */
const childElement = (/** @type {?} */ (componentElement.firstElementChild));
if (childElement) {
if (options.position.includes('right')) {
childElement.style.right = '0px';
}
if (options.position.includes('top')) {
childElement.style.bottom = '0px';
}
childElement.style.position = 'absolute';
}
this.resizeEventSubscription = this.resizeService.resize.pipe(take(1)).subscribe((/**
* @return {?}
*/
() => {
this.hide();
}));
}
/**
* Render component if not available, else display hidden component.
* @param {?} component Component class type.
* @param {?} parentElement Parent element to append the target component.
* @param {?} injector Component injector reference.
* @param {?} options Component loader options object.
* @return {?} Rendered component reference.
*/
show(component, parentElement, injector, options) {
options = Object.assign({
closeOnOutsideClick: true,
floatLeft: 0,
floatTop: 0,
position: 'bottom-left'
}, options);
if (this.componentReference) {
this.setPosition(parentElement, options);
this.isVisible = true;
return;
}
// 1. Create a component reference from the component
this.componentReference = this.componentFactoryResolver.resolveComponentFactory(component).create(injector);
if (options.context) {
Object.assign(this.componentReference.instance, options.context);
}
// 2. Attach component to the appRef so that it's inside the ng component tree
this.appRef.attachView(this.componentReference.hostView);
// 3. Get DOM element from component
/** @type {?} */
const domElem = (/** @type {?} */ (((/** @type {?} */ (this.componentReference.hostView))).rootNodes[0]));
this.setPosition(parentElement, options);
// 4. Append DOM element to the body
(options.relativeParentElement || parentElement).appendChild(domElem);
// Trigger change detection
this.componentReference.changeDetectorRef.markForCheck();
this.componentReference.changeDetectorRef.detectChanges();
this.isVisible = true;
if (options.closeOnOutsideClick) {
this.registerClickOutside(parentElement, this.componentReference.location.nativeElement);
}
return this.componentReference.instance;
}
/**
* Hide component if visible.
* @return {?} Rendered component reference.
*/
hide() {
if (this.componentReference) {
this.componentReference.location.nativeElement.style.display = 'none';
this.isVisible = false;
return this.componentReference.instance;
}
}
/**
* Toggle component display state or render if not available.
* @param {?} component Component class type.
* @param {?} parentElement Parent element to append the target component.
* @param {?} injector Component injector reference.
* @param {?=} options Component loader options object.
* @return {?} Rendered component reference.
*/
toggle(component, parentElement, injector, options) {
return this.isVisible ? this.hide() : this.show(component, parentElement, injector, options);
}
/**
* Dispose rendered component reference and bindings.
* @return {?}
*/
dispose() {
if (this.resizeEventSubscription) {
this.resizeEventSubscription.unsubscribe();
}
if (this.componentReference) {
this.appRef.detachView(this.componentReference.hostView);
this.componentReference.destroy();
}
if (this.clickListener) {
this.clickListener();
this.clickListener = null;
}
if (this.touchStartListener) {
this.touchStartListener();
this.touchStartListener = null;
}
this.componentReference = null;
}
}
if (false) {
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.componentReference;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.isVisible;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.clickListener;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.touchStartListener;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.resizeEventSubscription;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.componentFactoryResolver;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.appRef;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.globalRefService;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.renderer;
/**
* @type {?}
* @private
*/
PopoverComponentLoader.prototype.resizeService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wb3Zlci1jb21wb25lbnQtbG9hZGVyLmNsYXNzLmpzIiwic291cmNlUm9vdCI6Im5nOi8vb3JuYW1lbnR1bS8iLCJzb3VyY2VzIjpbInV0aWxpdHkvc2VydmljZXMvcG9wb3Zlci1jb21wb25lbnQtbG9hZGVyLmNsYXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFFQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7O0FBY3RDLE1BQU0sT0FBTyxzQkFBc0I7Ozs7Ozs7O0lBT2pDLFlBQ1Usd0JBQWtELEVBQ2xELE1BQXNCLEVBQ3RCLGdCQUFrQyxFQUNsQyxRQUFtQixFQUNuQixhQUE0QjtRQUo1Qiw2QkFBd0IsR0FBeEIsd0JBQXdCLENBQTBCO1FBQ2xELFdBQU0sR0FBTixNQUFNLENBQWdCO1FBQ3RCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFDbEMsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUNuQixrQkFBYSxHQUFiLGFBQWEsQ0FBZTtRQUVwQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUN6QixDQUFDOzs7Ozs7OztJQU9PLG9CQUFvQixDQUFDLEdBQUcsT0FBc0I7O2NBQzlDLGlCQUFpQjs7OztRQUFHLENBQUMsS0FBWSxFQUFFLEVBQUU7WUFDekMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJOzs7O1lBQUMsRUFBRSxDQUFDLEVBQUU7Z0JBQ3JCLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxtQkFBQSxLQUFLLENBQUMsTUFBTSxFQUFlLENBQUMsQ0FBQztZQUNsRCxDQUFDLEVBQUMsRUFBRTtnQkFDRixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7YUFDYjtRQUNILENBQUMsQ0FBQTtRQUVELElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLE9BQU8sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ2xGLElBQUksQ0FBQyxrQkFBa0Is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QTRDOzs7OztJQUM1QywyQ0FBMkI7Ozs7O0lBQzNCLCtDQUFrQzs7Ozs7SUFDbEMsb0RBQXVDOzs7OztJQUN2Qyx5REFBOEM7Ozs7O0lBRzVDLDBEQUEwRDs7Ozs7SUFDMUQsd0NBQThCOzs7OztJQUM5QixrREFBMEM7Ozs7O0lBQzFDLDBDQUEyQjs7Ozs7SUFDM0IsK0NBQW9DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0b3IsIENvbXBvbmVudEZhY3RvcnlSZXNvbHZlciwgRW1iZWRkZWRWaWV3UmVmLCBBcHBsaWNhdGlvblJlZiwgQ29tcG9uZW50UmVmLCBUeXBlLCBSZW5kZXJlcjIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IENvbXBvbmVudExvYWRlciB9IGZyb20gJy4vY29tcG9uZW50LWxvYWRlci5pbnRlcmZhY2UnO1xuXG5pbXBvcnQgeyBHbG9iYWxSZWZTZXJ2aWNlIH0gZnJvbSAnLi9nbG9iYWwtcmVmLnNlcnZpY2UnO1xuaW1wb3J0IHsgUmVzaXplU2VydmljZSB9IGZyb20gJy4vcmVzaXplLnNlcnZpY2UnO1xuXG5pbXBvcnQgeyBDb21wb25lbnRMb2FkZXJPcHRpb25zIH0gZnJvbSAnLi4vbW9kZWxzL2NvbXBvbmVudC1sb2FkZXItb3B0aW9ucy5tb2RlbCc7XG5cbi8qKlxuICogUG9wb3ZlciBkeW5hbWljIGNvbXBvbmVudCBsb2FkZXI7IFJlc3BvbnNpYmxlIG9mIGR5bmFtaWNhbGx5IHJlbmRlcmluZyBhbmd1bGFyIGNvbXBvbmVudHMgdG8gc2hvdyBwb3BvdmVyIGxheW91dC5cbiAqL1xuZXhwb3J0IGNsYXNzIFBvcG92ZXJDb21wb25lbnRMb2FkZXI8VD4gaW1wbGVtZW50cyBDb21wb25lbnRMb2FkZXI8VD4ge1xuICBwcml2YXRlIGNvbXBvbmVudFJlZmVyZW5jZTogQ29tcG9uZW50UmVmPFQ+O1xuICBwcml2YXRlIGlzVmlzaWJsZTogYm9vbGVhbjtcbiAgcHJpdmF0ZSBjbGlja0xpc3RlbmVyOiAoKSA9PiB2b2lkO1xuICBwcml2YXRlIHRvdWNoU3RhcnRMaXN0ZW5lcjogKCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZXNpemVFdmVudFN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY29tcG9uZW50RmFjdG9yeVJlc29sdmVyOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSBhcHBSZWY6IEFwcGxpY2F0aW9uUmVmLFxuICAgIHByaXZhdGUgZ2xvYmFsUmVmU2VydmljZTogR2xvYmFsUmVmU2VydmljZSxcbiAgICBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgcHJpdmF0ZSByZXNpemVTZXJ2aWNlOiBSZXNpemVTZXJ2aWNlXG4gICkge1xuICAgIHRoaXMuaXNWaXNpYmxlID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgY2xvc2Ugb24gY2xpY2sgb3V0c2lkZSBldmVudDsgSGlkZSBldmVudCBpcyB0cmlnZ2VyZWQgb25seSBpZiBjbGljayB0YXJnZXQgaXMgbm90IGluY2x1ZGVkIGluXG4gICAqIGV4Y2x1c2lvbiBlbGVtZW50cyBjb2xsZWN0aW9uLlxuICAgKiBAcGFyYW0gZXhjbHVkZSAtIEV4Y2x1ZGUgRE9NIGVsZW1lbnQgcmVmZXJlbmNlIGNvbGxlY3Rpb24uXG4gICAqL1xuICBwcml2YXRlIHJlZ2lzdGVyQ2xpY2tPdXRzaWRlKC4uLmV4Y2x1ZGU6IEhUTUxFbGVtZW50W10pOiB2b2lkIHtcbiAgICBjb25zdCB0cmFja091dHNpZGVDbGljayA9IChldmVudDogRXZlbnQpID0+IHtcbiAgICAgIGlmICghZXhjbHVkZS5zb21lKGVsID0+IHtcbiAgICAgICAgcmV0dXJuIGVsLmNvbnRhaW5zKGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCk7XG4gICAgICB9KSkge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5jbGlja0xpc3RlbmVyID0gdGhpcy5yZW5kZXJlci5saXN0ZW4oJ2RvY3VtZW50JywgJ2NsaWNrJywgdHJhY2tPdXRzaWRlQ2xpY2spO1xuICAgIHRoaXMudG91Y2hTdGFydExpc3RlbmVyID0gdGhpcy5yZW5kZXJlci5saXN0ZW4oJ2RvY3VtZW50JywgJ3RvdWNoc3RhcnQnLCB0cmFja091dHNpZGVDbGljayk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGR5bmFtaWMgcG9wb3ZlciBwb3NpdGlvbiByZWxhdGl2ZSB0byBwYXJlbnQuXG4gICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IFBhcmVudCBlbGVtZW50IHJlZmVyZW5jZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgQ29tcG9uZW50IGxvYWRlciBvcHRpb25zLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXRQb3NpdGlvbihwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCwgb3B0aW9uczogQ29tcG9uZW50TG9hZGVyT3B0aW9ucyk6IHZvaWQge1xuICAgIGNvbnN0IGhvbGRlckVsZW1lbnQgPSAgb3B0aW9ucy5yZWxhdGl2ZVBhcmVudEVsZW1lbnQgfHwgcGFyZW50RWxlbWVudDtcbiAgICBjb25zdCBib2R5Q2xpZW50UmVjdCA9IGhvbGRlckVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgZWxlbWVudENsaWVudFJlY3QgPSBwYXJlbnRFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgbGV0IGxlZnQgPSAwO1xuICAgIGxldCB0b3AgPSAwO1xuXG4gICAgaWYgKG9wdGlvbnMucG9zaXRpb24uaW5jbHVkZXMoJ3JpZ2h0JykpIHtcbiAgICAgIGxlZnQgPSBwYXJlbnRFbGVtZW50Lm9mZnNldFdpZHRoO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLnBvc2l0aW9uLmluY2x1ZGVzKCdib3R0b20nKSkge1xuICAgICAgdG9wID0gcGFyZW50RWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgfVxuXG4gICAgY29uc3QgY29tcG9uZW50RWxlbWVudCA9IHRoaXMuY29tcG9uZW50UmVmZXJlbmNlLmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgY29tcG9uZW50RWxlbWVudC5zdHlsZS50b3AgPSBgJHtlbGVtZW50Q2xpZW50UmVjdC50b3AgLSBib2R5Q2xpZW50UmVjdC50b3AgKyB0b3AgKyBvcHRpb25zLmZsb2F0VG9wfXB4YDtcbiAgICBjb21wb25lbnRFbGVtZW50LnN0eWxlLmxlZnQgPSBgJHtlbGVtZW50Q2xpZW50UmVjdC5sZWZ0IC0gYm9keUNsaWVudFJlY3QubGVmdCArIGxlZnQgKyBvcHRpb25zLmZsb2F0TGVmdH1weGA7XG4gICAgY29tcG9uZW50RWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgY29tcG9uZW50RWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblxuICAgIGNvbnN0IGNoaWxkRWxlbWVudCA9IGNvbXBvbmVudEVsZW1lbnQuZmlyc3RFbGVtZW50Q2hpbGQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgaWYgKGNoaWxkRWxlbWVudCkge1xuICAgICAgaWYgKG9wdGlvbnMucG9zaXRpb24uaW5jbHVkZXMoJ3JpZ2h0JykpIHtcbiAgICAgICAgY2hpbGRFbGVtZW50LnN0eWxlLnJpZ2h0ID0gJzBweCc7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnBvc2l0aW9uLmluY2x1ZGVzKCd0b3AnKSkge1xuICAgICAgICBjaGlsZEVsZW1lbnQuc3R5bGUuYm90dG9tID0gJzBweCc7XG4gICAgICB9XG5cbiAgICAgIGNoaWxkRWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgfVxuXG4gICAgdGhpcy5yZXNpemVFdmVudFN1YnNjcmlwdGlvbiA9IHRoaXMucmVzaXplU2VydmljZS5yZXNpemUucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5oaWRlKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIGNvbXBvbmVudCBpZiBub3QgYXZhaWxhYmxlLCBlbHNlIGRpc3BsYXkgaGlkZGVuIGNvbXBvbmVudC5cbiAgICogQHBhcmFtIGNvbXBvbmVudCBDb21wb25lbnQgY2xhc3MgdHlwZS5cbiAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgUGFyZW50IGVsZW1lbnQgdG8gYXBwZW5kIHRoZSB0YXJnZXQgY29tcG9uZW50LlxuICAgKiBAcGFyYW0gaW5qZWN0b3IgQ29tcG9uZW50IGluamVjdG9yIHJlZmVyZW5jZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgQ29tcG9uZW50IGxvYWRlciBvcHRpb25zIG9iamVjdC5cbiAgICogQHJldHVybiBSZW5kZXJlZCBjb21wb25lbnQgcmVmZXJlbmNlLlxuICAgKi9cbiAgcHVibGljIHNob3coY29tcG9uZW50OiBUeXBlPFQ+LCBwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCwgaW5qZWN0b3I6IEluamVjdG9yLCBvcHRpb25zOiBDb21wb25lbnRMb2FkZXJPcHRpb25zKTogVCB7XG4gICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICB7XG4gICAgICAgIGNsb3NlT25PdXRzaWRlQ2xpY2s6IHRydWUsXG4gICAgICAgIGZsb2F0TGVmdDogMCxcbiAgICAgICAgZmxvYXRUb3A6IDAsXG4gICAgICAgIHBvc2l0aW9uOiAnYm90dG9tLWxlZnQnXG4gICAgICB9LFxuICAgICAgb3B0aW9uc1xuICAgICk7XG5cbiAgICBpZiAodGhpcy5jb21wb25lbnRSZWZlcmVuY2UpIHtcbiAgICAgIHRoaXMuc2V0UG9zaXRpb24ocGFyZW50RWxlbWVudCwgb3B0aW9ucyk7XG4gICAgICB0aGlzLmlzVmlzaWJsZSA9IHRydWU7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gMS4gQ3JlYXRlIGEgY29tcG9uZW50IHJlZmVyZW5jZSBmcm9tIHRoZSBjb21wb25lbnRcbiAgICB0aGlzLmNvbXBvbmVudFJlZmVyZW5jZSA9IHRoaXMuY29tcG9uZW50RmFjdG9yeVJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KGNvbXBvbmVudCkuY3JlYXRlKGluamVjdG9yKTtcblxuICAgIGlmIChvcHRpb25zLmNvbnRleHQpIHtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5jb21wb25lbnRSZWZlcmVuY2UuaW5zdGFuY2UsIG9wdGlvbnMuY29udGV4dCk7XG4gICAgfVxuXG4gICAgLy8gMi4gQXR0YWNoIGNvbXBvbmVudCB0byB0aGUgYXBwUmVmIHNvIHRoYXQgaXQncyBpbnNpZGUgdGhlIG5nIGNvbXBvbmVudCB0cmVlXG4gICAgdGhpcy5hcHBSZWYuYXR0YWNoVmlldyh0aGlzLmNvbXBvbmVudFJlZmVyZW5jZS5ob3N0Vmlldyk7XG5cbiAgICAvLyAzLiBHZXQgRE9NIGVsZW1lbnQgZnJvbSBjb21wb25lbnRcbiAgICBjb25zdCBkb21FbGVtID0gKHRoaXMuY29tcG9uZW50UmVmZXJlbmNlLmhvc3RWaWV3IGFzIEVtYmVkZGVkVmlld1JlZjxhbnk+KS5yb290Tm9kZXNbMF0gYXMgSFRNTEVsZW1lbnQ7XG5cbiAgICB0aGlzLnNldFBvc2l0aW9uKHBhcmVudEVsZW1lbnQsIG9wdGlvbnMpO1xuXG4gICAgLy8gNC4gQXBwZW5kIERPTSBlbGVtZW50IHRvIHRoZSBib2R5XG4gICAgKG9wdGlvbnMucmVsYXRpdmVQYXJlbnRFbGVtZW50IHx8IHBhcmVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGRvbUVsZW0pO1xuXG4gICAgLy8gVHJpZ2dlciBjaGFuZ2UgZGV0ZWN0aW9uXG4gICAgdGhpcy5jb21wb25lbnRSZWZlcmVuY2UuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgdGhpcy5jb21wb25lbnRSZWZlcmVuY2UuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgdGhpcy5pc1Zpc2libGUgPSB0cnVlO1xuXG4gICAgaWYgKG9wdGlvbnMuY2xvc2VPbk91dHNpZGVDbGljaykge1xuICAgICAgdGhpcy5yZWdpc3RlckNsaWNrT3V0c2lkZShwYXJlbnRFbGVtZW50LCB0aGlzLmNvbXBvbmVudFJlZmVyZW5jZS5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnRSZWZlcmVuY2UuaW5zdGFuY2U7XG4gIH1cblxuICAvKipcbiAgICogSGlkZSBjb21wb25lbnQgaWYgdmlzaWJsZS5cbiAgICogQHJldHVybiBSZW5kZXJlZCBjb21wb25lbnQgcmVmZXJlbmNlLlxuICAgKi9cbiAgcHVibGljIGhpZGUoKTogVCB7XG4gICAgaWYgKHRoaXMuY29tcG9uZW50UmVmZXJlbmNlKSB7XG4gICAgICB0aGlzLmNvbXBvbmVudFJlZmVyZW5jZS5sb2NhdGlvbi5uYXRpdmVFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICB0aGlzLmlzVmlzaWJsZSA9IGZhbHNlO1xuICAgICAgcmV0dXJuIHRoaXMuY29tcG9uZW50UmVmZXJlbmNlLmluc3RhbmNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb2dnbGUgY29tcG9uZW50IGRpc3BsYXkgc3RhdGUgb3IgcmVuZGVyIGlmIG5vdCBhdmFpbGFibGUuXG4gICAqIEBwYXJhbSBjb21wb25lbnQgQ29tcG9uZW50IGNsYXNzIHR5cGUuXG4gICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IFBhcmVudCBlbGVtZW50IHRvIGFwcGVuZCB0aGUgdGFyZ2V0IGNvbXBvbmVudC5cbiAgICogQHBhcmFtIGluamVjdG9yIENvbXBvbmVudCBpbmplY3RvciByZWZlcmVuY2UuXG4gICAqIEBwYXJhbSBvcHRpb25zIENvbXBvbmVudCBsb2FkZXIgb3B0aW9ucyBvYmplY3QuXG4gICAqIEByZXR1cm4gUmVuZGVyZWQgY29tcG9uZW50IHJlZmVyZW5jZS5cbiAgICovXG4gIHB1YmxpYyB0b2dnbGUoY29tcG9uZW50OiBUeXBlPFQ+LCBwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCwgaW5qZWN0b3I6IEluamVjdG9yLCBvcHRpb25zPzogQ29tcG9uZW50TG9hZGVyT3B0aW9ucyk6IFQge1xuICAgIHJldHVybiB0aGlzLmlzVmlzaWJsZSA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KGNvbXBvbmVudCwgcGFyZW50RWxlbWVudCwgaW5qZWN0b3IsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3Bvc2UgcmVuZGVyZWQgY29tcG9uZW50IHJlZmVyZW5jZSBhbmQgYmluZGluZ3MuXG4gICAqL1xuICBwdWJsaWMgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5yZXNpemVFdmVudFN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5yZXNpemVFdmVudFN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbXBvbmVudFJlZmVyZW5jZSkge1xuICAgICAgdGhpcy5hcHBSZWYuZGV0YWNoVmlldyh0aGlzLmNvbXBvbmVudFJlZmVyZW5jZS5ob3N0Vmlldyk7XG4gICAgICB0aGlzLmNvbXBvbmVudFJlZmVyZW5jZS5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY2xpY2tMaXN0ZW5lcikge1xuICAgICAgdGhpcy5jbGlja0xpc3RlbmVyKCk7XG4gICAgICB0aGlzLmNsaWNrTGlzdGVuZXIgPSBudWxsO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRvdWNoU3RhcnRMaXN0ZW5lcikge1xuICAgICAgdGhpcy50b3VjaFN0YXJ0TGlzdGVuZXIoKTtcbiAgICAgIHRoaXMudG91Y2hTdGFydExpc3RlbmVyID0gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLmNvbXBvbmVudFJlZmVyZW5jZSA9IG51bGw7XG4gIH1cbn1cbiJdfQ==