UNPKG

@clarivate/angular-image-viewer

Version:

A configurable Angular image viewer component, compatible with Angular 7.x+

234 lines 32.4 kB
import { __assign, __decorate, __param } from "tslib"; import { Component, HostListener, Optional, Inject, Input, Output, EventEmitter, ViewChild } from '@angular/core'; import { CustomImageEvent } from './models/custom-image-event-model'; import { CdkDrag } from '@angular/cdk/drag-drop'; var DEFAULT_CONFIG = { btnClass: 'default', zoomFactor: 0.1, containerBackgroundColor: '#e4dede', primaryColor: '', wheelZoom: false, allowFullscreen: true, allowKeyboardNavigation: true, btnShow: { zoomIn: true, zoomOut: true, rotateClockwise: true, rotateCounterClockwise: true, next: true, prev: true }, btnIcons: { zoomIn: 'fa fa-plus', zoomOut: 'fa fa-minus', rotateClockwise: 'fa fa-refresh', rotateCounterClockwise: 'fa fa-undo', next: 'fa fa-chevron-right', prev: 'fa fa-chevron-left', fullscreen: 'fa fa-arrows-alt', } }; var AngularImageViewerComponent = /** @class */ (function () { function AngularImageViewerComponent(moduleConfig) { this.moduleConfig = moduleConfig; this.index = 0; this.footerTexts = [ 'Image', 'of', 'View previous or next image', 'using < > on the keyboard' ]; this.indexChange = new EventEmitter(); this.configChange = new EventEmitter(); this.customImageEvent = new EventEmitter(); this.styleHeight = '98vh'; this.style = { transform: '', msTransform: '', oTransform: '', webkitTransform: '' }; this.fullscreen = false; this.loading = true; this.isDragOn = false; this.scale = 1; this.rotation = 0; this.hovered = false; } AngularImageViewerComponent.prototype.ngOnChanges = function (changes) { if (changes.screenHeightOccupied) { this.styleHeight = 'calc(98vh - ' + this.screenHeightOccupied + 'px)'; } else if (changes.index) { this.reset(); } }; AngularImageViewerComponent.prototype.ngOnInit = function () { var merged = this.mergeConfig(DEFAULT_CONFIG, this.moduleConfig); this.config = this.mergeConfig(merged, this.config); this.triggerConfigBinding(); }; AngularImageViewerComponent.prototype.nextImage = function (event) { if (this.canNavigate(event) && this.index < this.src.length - 1) { this.loading = true; this.index++; this.triggerIndexBinding(); this.fireCustomEvent('next', this.index); this.reset(); } }; AngularImageViewerComponent.prototype.prevImage = function (event) { if (this.canNavigate(event) && this.index > 0) { this.loading = true; this.index--; this.triggerIndexBinding(); this.fireCustomEvent('prev', this.index); this.reset(); } }; AngularImageViewerComponent.prototype.zoomIn = function () { this.scale *= (1 + this.config.zoomFactor); this.fireCustomEvent('zoomIn', this.scale); this.updateStyle(); }; AngularImageViewerComponent.prototype.zoomOut = function () { if (this.scale > this.config.zoomFactor) { this.scale /= (1 + this.config.zoomFactor); } this.fireCustomEvent('zoomOut', this.scale); this.updateStyle(); }; AngularImageViewerComponent.prototype.scrollZoom = function (evt) { if (this.config.wheelZoom) { evt.deltaY > 0 ? this.zoomOut() : this.zoomIn(); return false; } }; AngularImageViewerComponent.prototype.rotateClockwise = function () { this.rotation += 90; this.fireCustomEvent('rotateClockwise', this.rotation); this.updateStyle(); }; AngularImageViewerComponent.prototype.rotateCounterClockwise = function () { this.rotation -= 90; this.updateStyle(); }; AngularImageViewerComponent.prototype.onLoad = function () { this.loading = false; }; AngularImageViewerComponent.prototype.onLoadStart = function () { this.loading = true; }; AngularImageViewerComponent.prototype.imageNotFound = function () { }; AngularImageViewerComponent.prototype.onDragStart = function (evt) { if (evt.source._dragRef._initialTransform && evt.source._dragRef._initialTransform.length > 0) { var myTranslate = evt.source._dragRef._initialTransform.split(' rotate')[0]; var myRotate = this.style.transform.split(' rotate')[1]; evt.source._dragRef._initialTransform = myTranslate + " rotate" + myRotate; } else { evt.source._dragRef._initialTransform = this.style.transform; } }; AngularImageViewerComponent.prototype.toggleFullscreen = function () { this.fullscreen = !this.fullscreen; if (!this.fullscreen) { this.reset(); } }; AngularImageViewerComponent.prototype.triggerIndexBinding = function () { this.indexChange.emit(this.index); }; AngularImageViewerComponent.prototype.triggerConfigBinding = function () { this.configChange.next(this.config); }; AngularImageViewerComponent.prototype.fireCustomEvent = function (name, imageIndex) { this.customImageEvent.emit(new CustomImageEvent(name, imageIndex)); }; AngularImageViewerComponent.prototype.reset = function () { this.scale = 1; this.rotation = 0; this.updateStyle(); this.cdkDrag.reset(); }; AngularImageViewerComponent.prototype.onMouseOver = function () { this.hovered = true; }; AngularImageViewerComponent.prototype.onMouseLeave = function () { this.hovered = false; }; AngularImageViewerComponent.prototype.canNavigate = function (event) { if (event.type === 'keyup') { return (this.config.allowKeyboardNavigation && this.hovered); } else if (event.type === 'click') { return this.hovered; } }; AngularImageViewerComponent.prototype.updateStyle = function () { this.style.transform = "rotate(" + this.rotation + "deg) scale(" + this.scale + ")"; }; AngularImageViewerComponent.prototype.mergeConfig = function (defaultValues, overrideValues) { var result = __assign({}, defaultValues); if (overrideValues) { result = __assign(__assign({}, defaultValues), overrideValues); if (overrideValues.btnIcons) { result.btnIcons = __assign(__assign({}, defaultValues.btnIcons), overrideValues.btnIcons); } } return result; }; AngularImageViewerComponent.ctorParameters = function () { return [ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: ['config',] }] } ]; }; __decorate([ ViewChild(CdkDrag, { static: true }) ], AngularImageViewerComponent.prototype, "cdkDrag", void 0); __decorate([ Input() ], AngularImageViewerComponent.prototype, "src", void 0); __decorate([ Input() ], AngularImageViewerComponent.prototype, "config", void 0); __decorate([ Input() ], AngularImageViewerComponent.prototype, "screenHeightOccupied", void 0); __decorate([ Input() ], AngularImageViewerComponent.prototype, "index", void 0); __decorate([ Input() ], AngularImageViewerComponent.prototype, "imageName", void 0); __decorate([ Input() ], AngularImageViewerComponent.prototype, "footerTexts", void 0); __decorate([ Output() ], AngularImageViewerComponent.prototype, "indexChange", void 0); __decorate([ Output() ], AngularImageViewerComponent.prototype, "configChange", void 0); __decorate([ Output() ], AngularImageViewerComponent.prototype, "customImageEvent", void 0); __decorate([ HostListener('window:keyup.ArrowRight', ['$event']) ], AngularImageViewerComponent.prototype, "nextImage", null); __decorate([ HostListener('window:keyup.ArrowLeft', ['$event']) ], AngularImageViewerComponent.prototype, "prevImage", null); __decorate([ HostListener('mouseover') ], AngularImageViewerComponent.prototype, "onMouseOver", null); __decorate([ HostListener('mouseleave') ], AngularImageViewerComponent.prototype, "onMouseLeave", null); AngularImageViewerComponent = __decorate([ Component({ // tslint:disable-next-line:component-selector selector: 'angular-image-viewer', template: "<div [appScreenfull]=\"fullscreen\" class=\"img-container\" [style.backgroundColor]=\"config.containerBackgroundColor\"\n (wheel)=\"scrollZoom($event)\">\n <div class=\"image-name\" *ngIf=\"imageName\">\n <span>{{imageName}}</span>\n </div>\n\n <div cdkDrag class=\"drag-element\">\n <img [src]=\"src[index]\" [ngStyle]=\"style\" alt=\"\"\n (cdkDragStarted)=\"onDragStart($event)\"\n (load)=\"onLoad()\" (loadstart)=\"onLoadStart()\" (error)=\"imageNotFound()\" />\n </div>\n\n <div class=\"spinner-container\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n </div>\n\n <div class=\"button-container\">\n <button type=\"button\" id=\"ngx-fs-btn\" [class]=\"config.btnClass\" (click)=\"toggleFullscreen()\"\n [style.color]=\"config.primaryColor\" *ngIf=\"config.allowFullscreen\">\n <span [class]=\"config.btnIcons.fullscreen\"></span>\n </button>\n\n <div class=\"button-container-bottom\">\n <button type=\"button\" [class]=\"config.btnClass\" *ngFor=\"let cBtn of config.customBtns\"\n [style.color]=\"config.primaryColor\" (click)=\"fireCustomEvent(cBtn.name, index)\">\n <span [class]=\"cBtn.icon\"></span>\n </button>\n\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow.rotateCounterClockwise\"\n [style.color]=\"config.primaryColor\" (click)=\"rotateCounterClockwise()\">\n <span [class]=\"config.btnIcons.rotateCounterClockwise\"></span>\n </button>\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow.rotateClockwise\"\n [style.color]=\"config.primaryColor\" (click)=\"rotateClockwise()\">\n <span [class]=\"config.btnIcons.rotateClockwise\"></span>\n </button>\n\n <div class=\"button-zoom-in-out-container\">\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow.zoomIn\"\n [style.color]=\"config.primaryColor\" (click)=\"zoomIn()\">\n <span [class]=\"config.btnIcons.zoomIn\"></span>\n </button>\n <button type=\"button\" [class]=\"config.btnClass\" *ngIf=\"config.btnShow.zoomOut\"\n [style.color]=\"config.primaryColor\" (click)=\"zoomOut()\">\n <span [class]=\"config.btnIcons.zoomOut\"></span>\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"nav-button-container\" *ngIf=\"src.length > 1\">\n <button type=\"button\" #prevImg [class]=\"config.btnClass\" (click)=\"prevImage($event); prevImg.blur()\"\n [style.color]=\"config.primaryColor\" [disabled]=\"index === 0\">\n <span [class]=\"config.btnIcons.prev\"></span>\n </button>\n <button type=\"button\" #nextImg [class]=\"config.btnClass\" (click)=\"nextImage($event); nextImg.blur()\"\n [style.color]=\"config.primaryColor\" [disabled]=\"index === src.length - 1\">\n <span [class]=\"config.btnIcons.next\"></span>\n </button>\n </div>\n <div class=\"footer-section\">\n <div class=\"image-txt-count-left-align\"><span>{{footerTexts[0]}} {{index + 1}} {{footerTexts[1]}} {{src.length}}</span></div>\n <div class=\"footer-txt-right-align\">\n <span class=\"footer-txt-right-align-title\" [style.color]=\"config.primaryColor\">{{footerTexts[2]}}</span>\n <span class=\"footer-txt-right-align-note\">{{footerTexts[3]}}</span>\n </div>\n </div>\n</div>\n", styles: [".img-container{position:relative;width:100%;height:100%;display:-webkit-box;display:flex;-webkit-box-pack:center;justify-content:center;-webkit-box-align:center;align-items:center;overflow:hidden}.img-container .drag-element{position:absolute;top:35px;right:78px;width:calc(100% - 156px);height:calc(100% - 85px);cursor:-webkit-grab;cursor:grab;text-align:center}.img-container .drag-element img{padding:0;max-width:100%;max-height:100%}.img-container .drag-element:active{cursor:-webkit-grabbing;cursor:grabbing}.img-container button{z-index:99}.img-container button:not(:disabled){cursor:pointer}#ngx-fs-btn{top:15px}button.default{height:24px;width:24px;border-radius:31px;opacity:.9;-webkit-transition:opacity .2s;transition:opacity .2s;font-size:12px;background:inherit;background-color:#fff;border:none;box-shadow:0 0 5px rgba(0,0,0,.3490196078)}button.default:focus{outline:0;opacity:1}button.default:hover{opacity:1}button.default:disabled{opacity:.3}.nav-button-container>button{position:relative;right:0;margin:0 10px}.nav-button-container{text-align:right;position:absolute;z-index:98;bottom:60px;left:0;right:10px}.nav-button-container button.default{height:30px;margin:0;font-size:14px}.nav-button-container button.default:first-child{border-radius:4px 0 0 4px}.nav-button-container button.default:last-child{margin-left:10px;border-radius:0 4px 4px 0}.button-container{position:absolute;top:10px;right:10px;width:24px;height:calc(100% - 115px);z-index:98}.button-container .button-container-bottom{position:absolute;bottom:0}.button-container .button-container-bottom button.default{margin-top:10px}.button-container .button-container-bottom .button-zoom-in-out-container{margin-top:15px}.button-container .button-container-bottom .button-zoom-in-out-container button.default{margin:0;border-radius:0;height:30px}.button-container .button-container-bottom .button-zoom-in-out-container button.default:first-child{margin-bottom:1px}.spinner-container{position:absolute;left:0;right:0;top:0;bottom:0;width:60px;height:60px;margin:auto;padding:10px;background-color:rgba(0,0,0,.4);border-radius:25%}.spinner{border-width:7px;border-style:solid;border-color:#ccc #ccc #222;border-radius:50%;height:100%;width:100%;box-sizing:border-box;-webkit-animation:2s linear infinite rotation;animation:2s linear infinite rotation}.footer-section{position:absolute;bottom:10px;left:0;width:100%;line-height:18px;z-index:98}.footer-section .image-txt-count-left-align{float:left;padding:0 10px;font-family:\"Source Sans Pro SemiBold\";font-size:14;color:#333}.footer-section .footer-txt-right-align{float:right;padding:0 10px;text-align:right}.footer-section .footer-txt-right-align span.footer-txt-right-align-title{display:block;font-family:\"Source Sans Pro SemiBold\";font-size:14}.footer-section .footer-txt-right-align span.footer-txt-right-align-note{color:#767676;font-family:\"Source Sans Pro\";font-size:12}.image-name{position:absolute;top:10px;left:10px;z-index:98;font-family:\"Source Sans Pro SemiBold\";font-size:16;color:#333}@keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(359deg)}}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(359deg)}}"] }), __param(0, Optional()), __param(0, Inject('config')) ], AngularImageViewerComponent); return AngularImageViewerComponent; }()); export { AngularImageViewerComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1pbWFnZS12aWV3ZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGNsYXJpdmF0ZS9hbmd1bGFyLWltYWdlLXZpZXdlci8iLCJzb3VyY2VzIjpbImxpYi9hbmd1bGFyLWltYWdlLXZpZXdlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFDdkUsWUFBWSxFQUE0QixTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFM0UsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDckUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRWpELElBQU0sY0FBYyxHQUFzQjtJQUN4QyxRQUFRLEVBQUUsU0FBUztJQUNuQixVQUFVLEVBQUUsR0FBRztJQUNmLHdCQUF3QixFQUFFLFNBQVM7SUFDbkMsWUFBWSxFQUFFLEVBQUU7SUFDaEIsU0FBUyxFQUFFLEtBQUs7SUFDaEIsZUFBZSxFQUFFLElBQUk7SUFDckIsdUJBQXVCLEVBQUUsSUFBSTtJQUM3QixPQUFPLEVBQUU7UUFDUCxNQUFNLEVBQUUsSUFBSTtRQUNaLE9BQU8sRUFBRSxJQUFJO1FBQ2IsZUFBZSxFQUFFLElBQUk7UUFDckIsc0JBQXNCLEVBQUUsSUFBSTtRQUM1QixJQUFJLEVBQUUsSUFBSTtRQUNWLElBQUksRUFBRSxJQUFJO0tBQ1g7SUFDRCxRQUFRLEVBQUU7UUFDUixNQUFNLEVBQUUsWUFBWTtRQUNwQixPQUFPLEVBQUUsYUFBYTtRQUN0QixlQUFlLEVBQUUsZUFBZTtRQUNoQyxzQkFBc0IsRUFBRSxZQUFZO1FBQ3BDLElBQUksRUFBRSxxQkFBcUI7UUFDM0IsSUFBSSxFQUFFLG9CQUFvQjtRQUMxQixVQUFVLEVBQUUsa0JBQWtCO0tBQy9CO0NBQ0YsQ0FBQztBQVFGO0lBOENFLHFD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b25hbCwgSW5qZWN0LCBJbnB1dCwgT3V0cHV0LFxuICBFdmVudEVtaXR0ZXIsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcywgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJbWFnZVZpZXdlckNvbmZpZyB9IGZyb20gJy4vbW9kZWxzL2ltYWdlLXZpZXdlci1jb25maWcubW9kZWwnO1xuaW1wb3J0IHsgQ3VzdG9tSW1hZ2VFdmVudCB9IGZyb20gJy4vbW9kZWxzL2N1c3RvbS1pbWFnZS1ldmVudC1tb2RlbCc7XG5pbXBvcnQgeyBDZGtEcmFnIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2RyYWctZHJvcCc7XG5cbmNvbnN0IERFRkFVTFRfQ09ORklHOiBJbWFnZVZpZXdlckNvbmZpZyA9IHtcbiAgYnRuQ2xhc3M6ICdkZWZhdWx0JyxcbiAgem9vbUZhY3RvcjogMC4xLFxuICBjb250YWluZXJCYWNrZ3JvdW5kQ29sb3I6ICcjZTRkZWRlJyxcbiAgcHJpbWFyeUNvbG9yOiAnJyxcbiAgd2hlZWxab29tOiBmYWxzZSxcbiAgYWxsb3dGdWxsc2NyZWVuOiB0cnVlLFxuICBhbGxvd0tleWJvYXJkTmF2aWdhdGlvbjogdHJ1ZSxcbiAgYnRuU2hvdzoge1xuICAgIHpvb21JbjogdHJ1ZSxcbiAgICB6b29tT3V0OiB0cnVlLFxuICAgIHJvdGF0ZUNsb2Nrd2lzZTogdHJ1ZSxcbiAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlOiB0cnVlLFxuICAgIG5leHQ6IHRydWUsXG4gICAgcHJldjogdHJ1ZVxuICB9LFxuICBidG5JY29uczoge1xuICAgIHpvb21JbjogJ2ZhIGZhLXBsdXMnLFxuICAgIHpvb21PdXQ6ICdmYSBmYS1taW51cycsXG4gICAgcm90YXRlQ2xvY2t3aXNlOiAnZmEgZmEtcmVmcmVzaCcsXG4gICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZTogJ2ZhIGZhLXVuZG8nLFxuICAgIG5leHQ6ICdmYSBmYS1jaGV2cm9uLXJpZ2h0JyxcbiAgICBwcmV2OiAnZmEgZmEtY2hldnJvbi1sZWZ0JyxcbiAgICBmdWxsc2NyZWVuOiAnZmEgZmEtYXJyb3dzLWFsdCcsXG4gIH1cbn07XG5cbkBDb21wb25lbnQoe1xuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Y29tcG9uZW50LXNlbGVjdG9yXG4gIHNlbGVjdG9yOiAnYW5ndWxhci1pbWFnZS12aWV3ZXInLFxuICB0ZW1wbGF0ZVVybDogJy4vYW5ndWxhci1pbWFnZS12aWV3ZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9hbmd1bGFyLWltYWdlLXZpZXdlci5jb21wb25lbnQuc2NzcyddXG59KVxuZXhwb3J0IGNsYXNzIEFuZ3VsYXJJbWFnZVZpZXdlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcblxuICBAVmlld0NoaWxkKENka0RyYWcsIHsgc3RhdGljOiB0cnVlIH0pIGNka0RyYWc6IENka0RyYWc7XG5cbiAgQElucHV0KClcbiAgc3JjOiBzdHJpbmdbXTtcblxuICBASW5wdXQoKVxuICBjb25maWc6IEltYWdlVmlld2VyQ29uZmlnO1xuXG4gIEBJbnB1dCgpXG4gIHNjcmVlbkhlaWdodE9jY3VwaWVkOiAwOyAgICAgICAgICAgICAvLyBJbiBQeFxuXG4gIEBJbnB1dCgpXG4gIGluZGV4ID0gMDtcblxuICBASW5wdXQoKVxuICBpbWFnZU5hbWU6IHN0cmluZztcblxuICBASW5wdXQoKVxuICBmb290ZXJUZXh0cyA9IFtcbiAgICAnSW1hZ2UnLFxuICAgICdvZicsXG4gICAgJ1ZpZXcgcHJldmlvdXMgb3IgbmV4dCBpbWFnZScsXG4gICAgJ3VzaW5nIDwgPiBvbiB0aGUga2V5Ym9hcmQnXG4gIF07XG5cbiAgQE91dHB1dCgpXG4gIGluZGV4Q2hhbmdlOiBFdmVudEVtaXR0ZXI8bnVtYmVyPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KClcbiAgY29uZmlnQ2hhbmdlOiBFdmVudEVtaXR0ZXI8SW1hZ2VWaWV3ZXJDb25maWc+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoKVxuICBjdXN0b21JbWFnZUV2ZW50OiBFdmVudEVtaXR0ZXI8Q3VzdG9tSW1hZ2VFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgc3R5bGVIZWlnaHQgPSAnOTh2aCc7XG5cbiAgcHVibGljIHN0eWxlID0geyB0cmFuc2Zvcm06ICcnLCBtc1RyYW5zZm9ybTogJycsIG9UcmFuc2Zvcm06ICcnLCB3ZWJraXRUcmFuc2Zvcm06ICcnIH07XG4gIHB1YmxpYyBmdWxsc2NyZWVuID0gZmFsc2U7XG4gIHB1YmxpYyBsb2FkaW5nID0gdHJ1ZTtcbiAgcHVibGljIGlzRHJhZ09uID0gZmFsc2U7XG4gIHByaXZhdGUgc2NhbGUgPSAxO1xuICBwcml2YXRlIHJvdGF0aW9uID0gMDtcbiAgcHJpdmF0ZSBob3ZlcmVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoQE9wdGlvbmFsKCkgQEluamVjdCgnY29uZmlnJykgcHVibGljIG1vZHVsZUNvbmZpZzogSW1hZ2VWaWV3ZXJDb25maWcpIHsgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoY2hhbmdlcy5zY3JlZW5IZWlnaHRPY2N1cGllZCkge1xuICAgICAgdGhpcy5zdHlsZUhlaWdodCA9ICdjYWxjKDk4dmggLSAnICsgdGhpcy5zY3JlZW5IZWlnaHRPY2N1cGllZCArICdweCknO1xuICAgIH0gZWxzZSBpZiAoY2hhbmdlcy5pbmRleCkge1xuICAgICAgdGhpcy5yZXNldCgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIGNvbnN0IG1lcmdlZCA9IHRoaXMubWVyZ2VDb25maWcoREVGQVVMVF9DT05GSUcsIHRoaXMubW9kdWxlQ29uZmlnKTtcbiAgICB0aGlzLmNvbmZpZyA9IHRoaXMubWVyZ2VDb25maWcobWVyZ2VkLCB0aGlzLmNvbmZpZyk7XG4gICAgdGhpcy50cmlnZ2VyQ29uZmlnQmluZGluZygpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleXVwLkFycm93UmlnaHQnLCBbJyRldmVudCddKVxuICBuZXh0SW1hZ2UoZXZlbnQpIHtcbiAgICBpZiAodGhpcy5jYW5OYXZpZ2F0ZShldmVudCkgJiYgdGhpcy5pbmRleCA8IHRoaXMuc3JjLmxlbmd0aCAtIDEpIHtcbiAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG4gICAgICB0aGlzLmluZGV4Kys7XG4gICAgICB0aGlzLnRyaWdnZXJJbmRleEJpbmRpbmcoKTtcbiAgICAgIHRoaXMuZmlyZUN1c3RvbUV2ZW50KCduZXh0JywgdGhpcy5pbmRleCk7XG4gICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleXVwLkFycm93TGVmdCcsIFsnJGV2ZW50J10pXG4gIHByZXZJbWFnZShldmVudCkge1xuICAgIGlmICh0aGlzLmNhbk5hdmlnYXRlKGV2ZW50KSAmJiB0aGlzLmluZGV4ID4gMCkge1xuICAgICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuaW5kZXgtLTtcbiAgICAgIHRoaXMudHJpZ2dlckluZGV4QmluZGluZygpO1xuICAgICAgdGhpcy5maXJlQ3VzdG9tRXZlbnQoJ3ByZXYnLCB0aGlzLmluZGV4KTtcbiAgICAgIHRoaXMucmVzZXQoKTtcbiAgICB9XG4gIH1cblxuICB6b29tSW4oKSB7XG4gICAgdGhpcy5zY2FsZSAqPSAoMSArIHRoaXMuY29uZmlnLnpvb21GYWN0b3IpO1xuICAgIHRoaXMuZmlyZUN1c3RvbUV2ZW50KCd6b29tSW4nLCB0aGlzLnNjYWxlKTtcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICB6b29tT3V0KCkge1xuICAgIGlmICh0aGlzLnNjYWxlID4gdGhpcy5jb25maWcuem9vbUZhY3Rvcikge1xuICAgICAgdGhpcy5zY2FsZSAvPSAoMSArIHRoaXMuY29uZmlnLnpvb21GYWN0b3IpO1xuICAgIH1cbiAgICB0aGlzLmZpcmVDdXN0b21FdmVudCgnem9vbU91dCcsIHRoaXMuc2NhbGUpO1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgfVxuXG4gIHNjcm9sbFpvb20oZXZ0KSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLndoZWVsWm9vbSkge1xuICAgICAgZXZ0LmRlbHRhWSA+IDAgPyB0aGlzLnpvb21PdXQoKSA6IHRoaXMuem9vbUluKCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcm90YXRlQ2xvY2t3aXNlKCkge1xuICAgIHRoaXMucm90YXRpb24gKz0gOTA7XG4gICAgdGhpcy5maXJlQ3VzdG9tRXZlbnQoJ3JvdGF0ZUNsb2Nrd2lzZScsIHRoaXMucm90YXRpb24pO1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgfVxuXG4gIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKSB7XG4gICAgdGhpcy5yb3RhdGlvbiAtPSA5MDtcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICBvbkxvYWQoKSB7XG4gICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gIH1cblxuICBvbkxvYWRTdGFydCgpIHtcbiAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuICB9XG5cbiAgaW1hZ2VOb3RGb3VuZCgpIHtcbiAgfVxuXG4gIG9uRHJhZ1N0YXJ0KGV2dCkge1xuICAgIGlmIChldnQuc291cmNlLl9kcmFnUmVmLl9pbml0aWFsVHJhbnNmb3JtICYmIGV2dC5zb3VyY2UuX2RyYWdSZWYuX2luaXRpYWxUcmFuc2Zvcm0ubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbXlUcmFuc2xhdGUgPSBldnQuc291cmNlLl9kcmFnUmVmLl9pbml0aWFsVHJhbnNmb3JtLnNwbGl0KCcgcm90YXRlJylbMF07XG4gICAgICBjb25zdCBteVJvdGF0ZSA9IHRoaXMuc3R5bGUudHJhbnNmb3JtLnNwbGl0KCcgcm90YXRlJylbMV07XG4gICAgICBldnQuc291cmNlLl9kcmFnUmVmLl9pbml0aWFsVHJhbnNmb3JtID0gYCR7bXlUcmFuc2xhdGV9IHJvdGF0ZSR7bXlSb3RhdGV9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgZXZ0LnNvdXJjZS5fZHJhZ1JlZi5faW5pdGlhbFRyYW5zZm9ybSA9IHRoaXMuc3R5bGUudHJhbnNmb3JtO1xuICAgIH1cbiAgfVxuXG4gIHRvZ2dsZUZ1bGxzY3JlZW4oKSB7XG4gICAgdGhpcy5mdWxsc2NyZWVuID0gIXRoaXMuZnVsbHNjcmVlbjtcbiAgICBpZiAoIXRoaXMuZnVsbHNjcmVlbikge1xuICAgICAgdGhpcy5yZXNldCgpO1xuICAgIH1cbiAgfVxuXG4gIHRyaWdnZXJJbmRleEJpbmRpbmcoKSB7XG4gICAgdGhpcy5pbmRleENoYW5nZS5lbWl0KHRoaXMuaW5kZXgpO1xuICB9XG5cbiAgdHJpZ2dlckNvbmZpZ0JpbmRpbmcoKSB7XG4gICAgdGhpcy5jb25maWdDaGFuZ2UubmV4dCh0aGlzLmNvbmZpZyk7XG4gIH1cblxuICBmaXJlQ3VzdG9tRXZlbnQobmFtZSwgaW1hZ2VJbmRleCkge1xuICAgIHRoaXMuY3VzdG9tSW1hZ2VFdmVudC5lbWl0KG5ldyBDdXN0b21JbWFnZUV2ZW50KG5hbWUsIGltYWdlSW5kZXgpKTtcbiAgfVxuXG4gIHJlc2V0KCkge1xuICAgIHRoaXMuc2NhbGUgPSAxO1xuICAgIHRoaXMucm90YXRpb24gPSAwO1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgICB0aGlzLmNka0RyYWcucmVzZXQoKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlb3ZlcicpXG4gIG9uTW91c2VPdmVyKCkge1xuICAgIHRoaXMuaG92ZXJlZCA9IHRydWU7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdtb3VzZWxlYXZlJylcbiAgb25Nb3VzZUxlYXZlKCkge1xuICAgIHRoaXMuaG92ZXJlZCA9IGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5OYXZpZ2F0ZShldmVudDogYW55KSB7XG4gICAgaWYgKGV2ZW50LnR5cGUgPT09ICdrZXl1cCcpIHtcbiAgICAgIHJldHVybiAodGhpcy5jb25maWcuYWxsb3dLZXlib2FyZE5hdmlnYXRpb24gJiYgdGhpcy5ob3ZlcmVkKTtcbiAgICB9IGVsc2UgaWYgKGV2ZW50LnR5cGUgPT09ICdjbGljaycpIHtcbiAgICAgIHJldHVybiB0aGlzLmhvdmVyZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVTdHlsZSgpIHtcbiAgICB0aGlzLnN0eWxlLnRyYW5zZm9ybSA9IGByb3RhdGUoJHt0aGlzLnJvdGF0aW9ufWRlZykgc2NhbGUoJHt0aGlzLnNjYWxlfSlgO1xuICB9XG5cbiAgcHJpdmF0ZSBtZXJnZUNvbmZpZyhkZWZhdWx0VmFsdWVzOiBJbWFnZVZpZXdlckNvbmZpZywgb3ZlcnJpZGVWYWx1ZXM6IEltYWdlVmlld2VyQ29uZmlnKTogSW1hZ2VWaWV3ZXJDb25maWcge1xuICAgIGxldCByZXN1bHQ6IEltYWdlVmlld2VyQ29uZmlnID0geyAuLi5kZWZhdWx0VmFsdWVzIH07XG4gICAgaWYgKG92ZXJyaWRlVmFsdWVzKSB7XG4gICAgICByZXN1bHQgPSB7IC4uLmRlZmF1bHRWYWx1ZXMsIC4uLm92ZXJyaWRlVmFsdWVzIH07XG5cbiAgICAgIGlmIChvdmVycmlkZVZhbHVlcy5idG5JY29ucykge1xuICAgICAgICByZXN1bHQuYnRuSWNvbnMgPSB7IC4uLmRlZmF1bHRWYWx1ZXMuYnRuSWNvbnMsIC4uLm92ZXJyaWRlVmFsdWVzLmJ0bkljb25zIH07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxufVxuIl19