UNPKG

@ngx-gallery/lightbox

Version:

Angular gallery directive that hooks the lightbox with the images automatically.

193 lines 16.5 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, Optional, ChangeDetectionStrategy, ElementRef, Inject } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { DOCUMENT } from '@angular/common'; import { FocusTrapFactory } from '@angular/cdk/a11y'; import { lightboxAnimation } from './lightbox.animation'; export class LightboxComponent { /** * @param {?} _document * @param {?} _focusTrapFactory * @param {?} _elementRef * @param {?} sanitizer */ constructor(_document, _focusTrapFactory, _elementRef, sanitizer) { this._document = _document; this._focusTrapFactory = _focusTrapFactory; this._elementRef = _elementRef; this.sanitizer = sanitizer; /** * State of the lightbox animation. */ this.state = 'enter'; this._savePreviouslyFocusedElement(); } /** * Callback, invoked whenever an animation on the host completes. * @param {?} event * @return {?} */ onAnimationDone(event) { if (event.toState === 'enter') { this._trapFocus(); } else { this.overlayRef.dispose(); this._restoreFocus(); } } /** * Moves the focus inside the focus trap. * @private * @return {?} */ _trapFocus() { if (!this._focusTrap) { this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement); } // If were to attempt to focus immediately, then the content of the lightbox would not yet be // ready in instances where change detection has to run first. To deal with this, we simply // wait for the microtask queue to be empty. this._focusTrap.focusInitialElementWhenReady(); } /** * Saves a reference to the element that was focused before the lightbox was opened. * @private * @return {?} */ _savePreviouslyFocusedElement() { if (this._document) { this._elementFocusedBeforeDialogWasOpened = (/** @type {?} */ (this._document.activeElement)); // Note that there is no focus method when rendering on the server. if (this._elementRef.nativeElement.focus) { // Move focus onto the lightbox immediately in order to prevent the user from accidentally // opening multiple dialogs at the same time. Needs to be async, because the element // may not be focusable immediately. Promise.resolve().then(() => this._elementRef.nativeElement.focus()); } } } /** * Restores focus to the element that was focused before the lightbox opened. * @private * @return {?} */ _restoreFocus() { /** @type {?} */ const toFocus = this._elementFocusedBeforeDialogWasOpened; // We need the extra check, because IE can set the `activeElement` to null in some cases. if (toFocus && typeof toFocus.focus === 'function') { toFocus.focus(); } if (this._focusTrap) { this._focusTrap.destroy(); } } } LightboxComponent.decorators = [ { type: Component, args: [{ selector: 'lightbox', changeDetection: ChangeDetectionStrategy.OnPush, animations: [lightboxAnimation], template: ` <gallery [id]="id" [destroyRef]="false" [skipInitConfig]="true"> <i class="g-btn-close" aria-label="Close" (click)="overlayRef.detach()" [innerHTML]="sanitizer.bypassSecurityTrustHtml(closeIcon)"></i> </gallery> `, host: { 'tabindex': '-1', 'aria-modal': 'true', '[attr.id]': '"lightbox-" + id', '[attr.role]': 'role', '[attr.aria-labelledby]': 'ariaLabel ? null : ariaLabelledBy', '[attr.aria-label]': 'ariaLabel', '[attr.aria-describedby]': 'ariaDescribedBy || null', '[@lightbox]': 'state', '(@lightbox.done)': 'onAnimationDone($event)', }, styles: ["::ng-deep lightbox{position:relative;display:block;width:1100px;height:800px;max-width:94vw;max-height:90vh;border-radius:4px;overflow:hidden;box-shadow:0 11px 15px -7px rgba(0,0,0,.2),0 24px 38px 3px rgba(0,0,0,.14),0 9px 46px 8px rgba(0,0,0,.12)}::ng-deep lightbox:focus{outline:0}::ng-deep lightbox gallery{overflow:hidden;margin:0;display:block;width:100%;height:100%}::ng-deep .g-backdrop{background-color:rgba(0,0,0,.32)}::ng-deep .fullscreen{width:100%}::ng-deep .fullscreen ::ng-deep lightbox{max-width:unset;max-height:unset;position:fixed;top:0;left:0;bottom:0;right:0;height:100%;width:100%;border-radius:0}::ng-deep .g-overlay{margin:auto}@media only screen and (max-width:480px){::ng-deep .g-overlay{width:100%}::ng-deep .g-overlay ::ng-deep lightbox{max-width:unset;max-height:unset;position:fixed;top:0;left:0;bottom:0;right:0;height:100%;width:100%;border-radius:0}}::ng-deep .g-btn-close{position:absolute;right:.9em;top:.9em;z-index:60;cursor:pointer;width:20px;height:20px}@media only screen and (max-width:480px){::ng-deep .g-btn-close{right:.7em;top:.7em}}"] }] } ]; /** @nocollapse */ LightboxComponent.ctorParameters = () => [ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] }, { type: FocusTrapFactory }, { type: ElementRef }, { type: DomSanitizer } ]; if (false) { /** * Gallery ref id * @type {?} */ LightboxComponent.prototype.id; /** * Overlay ref to close the lightbox * @type {?} */ LightboxComponent.prototype.overlayRef; /** * Close button svg data * @type {?} */ LightboxComponent.prototype.closeIcon; /** * State of the lightbox animation. * @type {?} */ LightboxComponent.prototype.state; /** * The ARIA role of the lightbox element. * @type {?} */ LightboxComponent.prototype.role; /** * Aria label to assign to the lightbox element * @type {?} */ LightboxComponent.prototype.ariaLabel; /** * ID of the element that should be considered as the lightbox's label. * @type {?} */ LightboxComponent.prototype.ariaLabelledBy; /** * ID of the element that describes the lightbox. * @type {?} */ LightboxComponent.prototype.ariaDescribedBy; /** * The class that traps and manages focus within the lightbox. * @type {?} * @private */ LightboxComponent.prototype._focusTrap; /** * Element that was focused before the lightbox was opened. Save this to restore upon close. * @type {?} * @private */ LightboxComponent.prototype._elementFocusedBeforeDialogWasOpened; /** * @type {?} * @private */ LightboxComponent.prototype._document; /** * @type {?} * @private */ LightboxComponent.prototype._focusTrapFactory; /** * @type {?} * @private */ LightboxComponent.prototype._elementRef; /** @type {?} */ LightboxComponent.prototype.sanitizer; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRib3guY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5neC1nYWxsZXJ5L2xpZ2h0Ym94LyIsInNvdXJjZXMiOlsibGliL2xpZ2h0Ym94LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqRyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDekQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRzNDLE9BQU8sRUFBYSxnQkFBZ0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBeUJ6RCxNQUFNLE9BQU8saUJBQWlCOzs7Ozs7O0lBZ0M1QixZQUFrRCxTQUFjLEVBQzVDLGlCQUFtQyxFQUNuQyxXQUF1QixFQUN4QixTQUF1QjtRQUhRLGNBQVMsR0FBVCxTQUFTLENBQUs7UUFDNUMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFrQjtRQUNuQyxnQkFBVyxHQUFYLFdBQVcsQ0FBWTtRQUN4QixjQUFTLEdBQVQsU0FBUyxDQUFjOzs7O1FBdkIxQyxVQUFLLEdBQThCLE9BQU8sQ0FBQztRQXdCekMsSUFBSSxDQUFDLDZCQUE2QixFQUFFLENBQUM7SUFDdkMsQ0FBQzs7Ozs7O0lBR0QsZUFBZSxDQUFDLEtBQXFCO1FBQ25DLElBQUksS0FBSyxDQUFDLE9BQU8sS0FBSyxPQUFPLEVBQUU7WUFDN0IsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1NBQ25CO2FBQU07WUFDTCxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztTQUN0QjtJQUNILENBQUM7Ozs7OztJQUdPLFVBQVU7UUFDaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDcEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDakY7UUFDRCw2RkFBNkY7UUFDN0YsMkZBQTJGO1FBQzNGLDRDQUE0QztRQUM1QyxJQUFJLENBQUMsVUFBVSxDQUFDLDRCQUE0QixFQUFFLENBQUM7SUFDakQsQ0FBQzs7Ozs7O0lBR08sNkJBQTZCO1FBQ25DLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNsQixJQUFJLENBQUMsb0NBQW9DLEdBQUcsbUJBQUEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQWUsQ0FBQztZQUV4RixtRUFBbUU7WUFDbkUsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUU7Z0JBQ3hDLDBGQUEwRjtnQkFDMUYsb0ZBQW9GO2dCQUNwRixvQ0FBb0M7Z0JBQ3BDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQzthQUN0RTtTQUNGO0lBQ0gsQ0FBQzs7Ozs7O0lBR08sYUFBYTs7Y0FDYixPQUFPLEdBQUcsSUFBSSxDQUFDLG9DQUFvQztRQUV6RCx5RkFBeUY7UUFDekYsSUFBSSxPQUFPLElBQUksT0FBTyxPQUFPLENBQUMsS0FBSyxLQUFLLFVBQVUsRUFBRTtZQUNsRCxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDakI7UUFFRCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUMzQjtJQUNILENBQUM7OztZQTlHRixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLFVBQVU7Z0JBQ3BCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO2dCQUMvQyxVQUFVLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQztnQkFFL0IsUUFBUSxFQUFFOzs7OztHQUtUO2dCQUNELElBQUksRUFBRTtvQkFDSixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsWUFBWSxFQUFFLE1BQU07b0JBQ3BCLFdBQVcsRUFBRSxrQkFBa0I7b0JBQy9CLGFBQWEsRUFBRSxNQUFNO29CQUNyQix3QkFBd0IsRUFBRSxtQ0FBbUM7b0JBQzdELG1CQUFtQixFQUFFLFdBQVc7b0JBQ2hDLHlCQUF5QixFQUFFLHlCQUF5QjtvQkFDcEQsYUFBYSxFQUFFLE9BQU87b0JBQ3RCLGtCQUFrQixFQUFFLHlCQUF5QjtpQkFDOUM7O2FBQ0Y7Ozs7NENBaUNjLFFBQVEsWUFBSSxNQUFNLFNBQUMsUUFBUTtZQTFEdEIsZ0JBQWdCO1lBTG1CLFVBQVU7WUFDeEQsWUFBWTs7Ozs7OztJQWlDbkIsK0JBQVc7Ozs7O0lBR1gsdUNBQXVCOzs7OztJQUd2QixzQ0FBa0I7Ozs7O0lBR2xCLGtDQUEyQzs7Ozs7SUFHM0MsaUNBQWE7Ozs7O0lBR2Isc0NBQWtCOzs7OztJQUdsQiwyQ0FBdUI7Ozs7O0lBR3ZCLDRDQUF3Qjs7Ozs7O0lBR3hCLHVDQUE4Qjs7Ozs7O0lBRzlCLGlFQUEwRDs7Ozs7SUFFOUMsc0NBQW9EOzs7OztJQUNwRCw4Q0FBMkM7Ozs7O0lBQzNDLHdDQUErQjs7SUFDL0Isc0NBQThCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPcHRpb25hbCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIEVsZW1lbnRSZWYsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRG9tU2FuaXRpemVyIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5pbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBbmltYXRpb25FdmVudCB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgT3ZlcmxheVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9vdmVybGF5JztcbmltcG9ydCB7IEZvY3VzVHJhcCwgRm9jdXNUcmFwRmFjdG9yeSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7IGxpZ2h0Ym94QW5pbWF0aW9uIH0gZnJvbSAnLi9saWdodGJveC5hbmltYXRpb24nO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWdodGJveCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBhbmltYXRpb25zOiBbbGlnaHRib3hBbmltYXRpb25dLFxuICBzdHlsZVVybHM6IFsnLi9saWdodGJveC5jb21wb25lbnQuc2NzcyddLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxnYWxsZXJ5IFtpZF09XCJpZFwiIFtkZXN0cm95UmVmXT1cImZhbHNlXCIgW3NraXBJbml0Q29uZmlnXT1cInRydWVcIj5cbiAgICAgIDxpIGNsYXNzPVwiZy1idG4tY2xvc2VcIiBhcmlhLWxhYmVsPVwiQ2xvc2VcIiAoY2xpY2spPVwib3ZlcmxheVJlZi5kZXRhY2goKVwiXG4gICAgICAgICBbaW5uZXJIVE1MXT1cInNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0SHRtbChjbG9zZUljb24pXCI+PC9pPlxuICAgIDwvZ2FsbGVyeT5cbiAgYCxcbiAgaG9zdDoge1xuICAgICd0YWJpbmRleCc6ICctMScsXG4gICAgJ2FyaWEtbW9kYWwnOiAndHJ1ZScsXG4gICAgJ1thdHRyLmlkXSc6ICdcImxpZ2h0Ym94LVwiICsgaWQnLFxuICAgICdbYXR0ci5yb2xlXSc6ICdyb2xlJyxcbiAgICAnW2F0dHIuYXJpYS1sYWJlbGxlZGJ5XSc6ICdhcmlhTGFiZWwgPyBudWxsIDogYXJpYUxhYmVsbGVkQnknLFxuICAgICdbYXR0ci5hcmlhLWxhYmVsXSc6ICdhcmlhTGFiZWwnLFxuICAgICdbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XSc6ICdhcmlhRGVzY3JpYmVkQnkgfHwgbnVsbCcsXG4gICAgJ1tAbGlnaHRib3hdJzogJ3N0YXRlJyxcbiAgICAnKEBsaWdodGJveC5kb25lKSc6ICdvbkFuaW1hdGlvbkRvbmUoJGV2ZW50KScsXG4gIH1cbn0pXG5leHBvcnQgY2xhc3MgTGlnaHRib3hDb21wb25lbnQge1xuXG4gIC8qKiBHYWxsZXJ5IHJlZiBpZCAqL1xuICBpZDogc3RyaW5nO1xuXG4gIC8qKiBPdmVybGF5IHJlZiB0byBjbG9zZSB0aGUgbGlnaHRib3ggKi9cbiAgb3ZlcmxheVJlZjogT3ZlcmxheVJlZjtcblxuICAvKiogQ2xvc2UgYnV0dG9uIHN2ZyBkYXRhICovXG4gIGNsb3NlSWNvbjogc3RyaW5nO1xuXG4gIC8qKiBTdGF0ZSBvZiB0aGUgbGlnaHRib3ggYW5pbWF0aW9uLiAqL1xuICBzdGF0ZTogJ3ZvaWQnIHwgJ2VudGVyJyB8ICdleGl0JyA9ICdlbnRlcic7XG5cbiAgLyoqIFRoZSBBUklBIHJvbGUgb2YgdGhlIGxpZ2h0Ym94IGVsZW1lbnQuICovXG4gIHJvbGU6IHN0cmluZztcblxuICAvKiogQXJpYSBsYWJlbCB0byBhc3NpZ24gdG8gdGhlIGxpZ2h0Ym94IGVsZW1lbnQgKi9cbiAgYXJpYUxhYmVsOiBzdHJpbmc7XG5cbiAgLyoqIElEIG9mIHRoZSBlbGVtZW50IHRoYXQgc2hvdWxkIGJlIGNvbnNpZGVyZWQgYXMgdGhlIGxpZ2h0Ym94J3MgbGFiZWwuICovXG4gIGFyaWFMYWJlbGxlZEJ5OiBzdHJpbmc7XG5cbiAgLyoqIElEIG9mIHRoZSBlbGVtZW50IHRoYXQgZGVzY3JpYmVzIHRoZSBsaWdodGJveC4gKi9cbiAgYXJpYURlc2NyaWJlZEJ5OiBzdHJpbmc7XG5cbiAgLyoqIFRoZSBjbGFzcyB0aGF0IHRyYXBzIGFuZCBtYW5hZ2VzIGZvY3VzIHdpdGhpbiB0aGUgbGlnaHRib3guICovXG4gIHByaXZhdGUgX2ZvY3VzVHJhcDogRm9jdXNUcmFwO1xuXG4gIC8qKiBFbGVtZW50IHRoYXQgd2FzIGZvY3VzZWQgYmVmb3JlIHRoZSBsaWdodGJveCB3YXMgb3BlbmVkLiBTYXZlIHRoaXMgdG8gcmVzdG9yZSB1cG9uIGNsb3NlLiAqL1xuICBwcml2YXRlIF9lbGVtZW50Rm9jdXNlZEJlZm9yZURpYWxvZ1dhc09wZW5lZDogSFRNTEVsZW1lbnQ7XG5cbiAgY29uc3RydWN0b3IoQE9wdGlvbmFsKCkgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBfZG9jdW1lbnQ6IGFueSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfZm9jdXNUcmFwRmFjdG9yeTogRm9jdXNUcmFwRmFjdG9yeSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgICAgICAgcHVibGljIHNhbml0aXplcjogRG9tU2FuaXRpemVyKSB7XG4gICAgdGhpcy5fc2F2ZVByZXZpb3VzbHlGb2N1c2VkRWxlbWVudCgpO1xuICB9XG5cbiAgLyoqIENhbGxiYWNrLCBpbnZva2VkIHdoZW5ldmVyIGFuIGFuaW1hdGlvbiBvbiB0aGUgaG9zdCBjb21wbGV0ZXMuICovXG4gIG9uQW5pbWF0aW9uRG9uZShldmVudDogQW5pbWF0aW9uRXZlbnQpIHtcbiAgICBpZiAoZXZlbnQudG9TdGF0ZSA9PT0gJ2VudGVyJykge1xuICAgICAgdGhpcy5fdHJhcEZvY3VzKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMub3ZlcmxheVJlZi5kaXNwb3NlKCk7XG4gICAgICB0aGlzLl9yZXN0b3JlRm9jdXMoKTtcbiAgICB9XG4gIH1cblxuICAvKiogTW92ZXMgdGhlIGZvY3VzIGluc2lkZSB0aGUgZm9jdXMgdHJhcC4gKi9cbiAgcHJpdmF0ZSBfdHJhcEZvY3VzKCkge1xuICAgIGlmICghdGhpcy5fZm9jdXNUcmFwKSB7XG4gICAgICB0aGlzLl9mb2N1c1RyYXAgPSB0aGlzLl9mb2N1c1RyYXBGYWN0b3J5LmNyZWF0ZSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpO1xuICAgIH1cbiAgICAvLyBJZiB3ZXJlIHRvIGF0dGVtcHQgdG8gZm9jdXMgaW1tZWRpYXRlbHksIHRoZW4gdGhlIGNvbnRlbnQgb2YgdGhlIGxpZ2h0Ym94IHdvdWxkIG5vdCB5ZXQgYmVcbiAgICAvLyByZWFkeSBpbiBpbnN0YW5jZXMgd2hlcmUgY2hhbmdlIGRldGVjdGlvbiBoYXMgdG8gcnVuIGZpcnN0LiBUbyBkZWFsIHdpdGggdGhpcywgd2Ugc2ltcGx5XG4gICAgLy8gd2FpdCBmb3IgdGhlIG1pY3JvdGFzayBxdWV1ZSB0byBiZSBlbXB0eS5cbiAgICB0aGlzLl9mb2N1c1RyYXAuZm9jdXNJbml0aWFsRWxlbWVudFdoZW5SZWFkeSgpO1xuICB9XG5cbiAgLyoqIFNhdmVzIGEgcmVmZXJlbmNlIHRvIHRoZSBlbGVtZW50IHRoYXQgd2FzIGZvY3VzZWQgYmVmb3JlIHRoZSBsaWdodGJveCB3YXMgb3BlbmVkLiAqL1xuICBwcml2YXRlIF9zYXZlUHJldmlvdXNseUZvY3VzZWRFbGVtZW50KCkge1xuICAgIGlmICh0aGlzLl9kb2N1bWVudCkge1xuICAgICAgdGhpcy5fZWxlbWVudEZvY3VzZWRCZWZvcmVEaWFsb2dXYXNPcGVuZWQgPSB0aGlzLl9kb2N1bWVudC5hY3RpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xuXG4gICAgICAvLyBOb3RlIHRoYXQgdGhlcmUgaXMgbm8gZm9jdXMgbWV0aG9kIHdoZW4gcmVuZGVyaW5nIG9uIHRoZSBzZXJ2ZXIuXG4gICAgICBpZiAodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmZvY3VzKSB7XG4gICAgICAgIC8vIE1vdmUgZm9jdXMgb250byB0aGUgbGlnaHRib3ggaW1tZWRpYXRlbHkgaW4gb3JkZXIgdG8gcHJldmVudCB0aGUgdXNlciBmcm9tIGFjY2lkZW50YWxseVxuICAgICAgICAvLyBvcGVuaW5nIG11bHRpcGxlIGRpYWxvZ3MgYXQgdGhlIHNhbWUgdGltZS4gTmVlZHMgdG8gYmUgYXN5bmMsIGJlY2F1c2UgdGhlIGVsZW1lbnRcbiAgICAgICAgLy8gbWF5IG5vdCBiZSBmb2N1c2FibGUgaW1tZWRpYXRlbHkuXG4gICAgICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmZvY3VzKCkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKiBSZXN0b3JlcyBmb2N1cyB0byB0aGUgZWxlbWVudCB0aGF0IHdhcyBmb2N1c2VkIGJlZm9yZSB0aGUgbGlnaHRib3ggb3BlbmVkLiAqL1xuICBwcml2YXRlIF9yZXN0b3JlRm9jdXMoKSB7XG4gICAgY29uc3QgdG9Gb2N1cyA9IHRoaXMuX2VsZW1lbnRGb2N1c2VkQmVmb3JlRGlhbG9nV2FzT3BlbmVkO1xuXG4gICAgLy8gV2UgbmVlZCB0aGUgZXh0cmEgY2hlY2ssIGJlY2F1c2UgSUUgY2FuIHNldCB0aGUgYGFjdGl2ZUVsZW1lbnRgIHRvIG51bGwgaW4gc29tZSBjYXNlcy5cbiAgICBpZiAodG9Gb2N1cyAmJiB0eXBlb2YgdG9Gb2N1cy5mb2N1cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdG9Gb2N1cy5mb2N1cygpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9mb2N1c1RyYXApIHtcbiAgICAgIHRoaXMuX2ZvY3VzVHJhcC5kZXN0cm95KCk7XG4gICAgfVxuICB9XG59XG4iXX0=