UNPKG

@udhsin/ngx-image-viewer

Version:

A configurable Angular image viewer component, compatible with Angular 2+

206 lines 25.6 kB
import { __decorate, __param } from "tslib"; import { Component, Input, Optional, Inject, Output, EventEmitter, HostListener, } from '@angular/core'; import { CustomEvent } from './ngx-imageviewer-config.model'; const DEFAULT_CONFIG = { btnClass: 'default', zoomFactor: 0.1, containerBackgroundColor: '#ccc', wheelZoom: false, allowFullscreen: true, allowKeyboardNavigation: true, alignCenter: 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-repeat', rotateCounterClockwise: 'fa fa-undo', next: 'fa fa-arrow-right', prev: 'fa fa-arrow-left', fullscreen: 'fa fa-arrows-alt', }, }; let ImageViewerComponent = class ImageViewerComponent { constructor(moduleConfig) { this.moduleConfig = moduleConfig; this.index = 0; this.indexChange = new EventEmitter(); this.configChange = new EventEmitter(); this.customEvent = new EventEmitter(); this.style = { transform: '', msTransform: '', oTransform: '', webkitTransform: '', }; this.fullscreen = false; this.loading = true; this.scale = 1; this.rotation = 0; this.translateX = 0; this.translateY = 0; this.hovered = false; } ngOnInit() { const merged = this.mergeConfig(DEFAULT_CONFIG, this.moduleConfig); this.config = this.mergeConfig(merged, this.config); this.triggerConfigBinding(); } nextImage(event) { if (this.canNavigate(event) && this.index < this.src.length - 1) { this.loading = true; this.index++; this.triggerIndexBinding(); this.reset(); } } prevImage(event) { if (this.canNavigate(event) && this.index > 0) { this.loading = true; this.index--; this.triggerIndexBinding(); this.reset(); } } zoomIn() { this.scale *= 1 + this.config.zoomFactor; this.updateStyle(); } zoomOut() { if (this.scale > this.config.zoomFactor) { this.scale /= 1 + this.config.zoomFactor; } this.updateStyle(); } scrollZoom(evt) { if (this.config.wheelZoom) { evt.deltaY > 0 ? this.zoomOut() : this.zoomIn(); return false; } } rotateClockwise() { this.rotation += 90; this.updateStyle(); } rotateCounterClockwise() { this.rotation -= 90; this.updateStyle(); } onLoad() { this.loading = false; } onLoadStart() { this.loading = true; } onDragOver(evt) { this.translateX += evt.clientX - this.prevX; this.translateY += evt.clientY - this.prevY; this.prevX = evt.clientX; this.prevY = evt.clientY; this.updateStyle(); } onDragStart(evt) { if (evt.dataTransfer && evt.dataTransfer.setDragImage) { evt.dataTransfer.setDragImage(evt.target.nextElementSibling, 0, 0); } this.prevX = evt.clientX; this.prevY = evt.clientY; } toggleFullscreen() { this.fullscreen = !this.fullscreen; if (!this.fullscreen) { this.reset(); } } triggerIndexBinding() { this.indexChange.emit(this.index); } triggerConfigBinding() { this.configChange.next(this.config); } fireCustomEvent(name, imageIndex) { this.customEvent.emit(new CustomEvent(name, imageIndex)); } reset() { this.scale = 1; this.rotation = 0; this.translateX = 0; this.translateY = 0; this.updateStyle(); } onMouseOver() { this.hovered = true; } onMouseLeave() { this.hovered = false; } canNavigate(event) { return (event == null || (this.config.allowKeyboardNavigation && this.hovered)); } updateStyle() { this.style.transform = `translate(${this.translateX}px, ${this.translateY}px) rotate(${this.rotation}deg) scale(${this.scale})`; this.style.msTransform = this.style.transform; this.style.webkitTransform = this.style.transform; this.style.oTransform = this.style.transform; } mergeConfig(defaultValues, overrideValues) { let result = Object.assign({}, defaultValues); if (overrideValues) { result = Object.assign(Object.assign({}, defaultValues), overrideValues); if (overrideValues.btnIcons) { result.btnIcons = Object.assign(Object.assign({}, defaultValues.btnIcons), overrideValues.btnIcons); } } return result; } }; ImageViewerComponent.ctorParameters = () => [ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: ['config',] }] } ]; __decorate([ Input() ], ImageViewerComponent.prototype, "src", void 0); __decorate([ Input() ], ImageViewerComponent.prototype, "index", void 0); __decorate([ Input() ], ImageViewerComponent.prototype, "config", void 0); __decorate([ Output() ], ImageViewerComponent.prototype, "indexChange", void 0); __decorate([ Output() ], ImageViewerComponent.prototype, "configChange", void 0); __decorate([ Output() ], ImageViewerComponent.prototype, "customEvent", void 0); __decorate([ HostListener('window:keyup.ArrowRight', ['$event']) ], ImageViewerComponent.prototype, "nextImage", null); __decorate([ HostListener('window:keyup.ArrowLeft', ['$event']) ], ImageViewerComponent.prototype, "prevImage", null); __decorate([ HostListener('mouseover') ], ImageViewerComponent.prototype, "onMouseOver", null); __decorate([ HostListener('mouseleave') ], ImageViewerComponent.prototype, "onMouseLeave", null); ImageViewerComponent = __decorate([ Component({ selector: 'ngx-image-viewer', template: "<div\r\n [ngxToggleFullscreen]=\"fullscreen\"\r\n class=\"img-container\"\r\n [ngClass]=\"{'align-center': config.alignCenter}\"\r\n [style.backgroundColor]=\"config.containerBackgroundColor\"\r\n (wheel)=\"scrollZoom($event)\"\r\n (dragover)=\"onDragOver($event)\"\r\n>\r\n <img\r\n [src]=\"src[index]\"\r\n [ngStyle]=\"style\"\r\n alt=\"Image not found...\"\r\n (dragstart)=\"onDragStart($event)\"\r\n (load)=\"onLoad()\"\r\n (loadstart)=\"onLoadStart()\"\r\n />\r\n <!-- Div below will be used to hide the 'ghost' image when dragging -->\r\n <div></div>\r\n <div class=\"spinner-container\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n\r\n <button\r\n type=\"button\"\r\n [class]=\"config.btnClass\"\r\n *ngIf=\"config.btnShow.rotateCounterClockwise\"\r\n (click)=\"rotateCounterClockwise()\"\r\n >\r\n <span [class]=\"config.btnIcons.rotateCounterClockwise\"></span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n [class]=\"config.btnClass\"\r\n *ngIf=\"config.btnShow.rotateClockwise\"\r\n (click)=\"rotateClockwise()\"\r\n >\r\n <span [class]=\"config.btnIcons.rotateClockwise\"></span>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n [class]=\"config.btnClass\"\r\n *ngIf=\"config.btnShow.zoomOut\"\r\n (click)=\"zoomOut()\"\r\n >\r\n <span [class]=\"config.btnIcons.zoomOut\"></span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n [class]=\"config.btnClass\"\r\n *ngIf=\"config.btnShow.zoomIn\"\r\n (click)=\"zoomIn()\"\r\n >\r\n <span [class]=\"config.btnIcons.zoomIn\"></span>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n [class]=\"config.btnClass\"\r\n *ngFor=\"let cBtn of config.customBtns\"\r\n (click)=\"fireCustomEvent(cBtn.name, index)\"\r\n >\r\n <span [class]=\"cBtn.icon\"></span>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n id=\"ngx-fs-btn\"\r\n [class]=\"config.btnClass\"\r\n (click)=\"toggleFullscreen()\"\r\n *ngIf=\"config.allowFullscreen\"\r\n >\r\n <span [class]=\"config.btnIcons.fullscreen\"></span>\r\n </button>\r\n\r\n <div class=\"nav-button-container\" *ngIf=\"src.length > 1\">\r\n <button\r\n type=\"button\"\r\n [class]=\"config.btnClass\"\r\n (click)=\"prevImage($event)\"\r\n [disabled]=\"index === 0\"\r\n >\r\n <span [class]=\"config.btnIcons.prev\"></span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n [class]=\"config.btnClass\"\r\n (click)=\"nextImage($event)\"\r\n [disabled]=\"index === src.length - 1\"\r\n >\r\n <span [class]=\"config.btnIcons.next\"></span>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".img-container{height:100%;width:100%;overflow:hidden;position:relative}.img-container.align-center{display:flex}.img-container.align-center img{margin:auto!important}.img-container img{z-index:2;margin:0 auto;display:block;max-width:100%;max-height:100%}.img-container button{z-index:99;position:absolute;right:15px}.img-container button:not(:disabled){cursor:pointer}.img-container button.default{height:40px;width:40px;border:1px solid #555;border-radius:50%;background-color:#fff;opacity:.7;transition:opacity .2s}.img-container button.default:hover{opacity:1}.img-container button.default:disabled{opacity:.25}.img-container>button:nth-of-type(1):not(#ngx-fs-btn){bottom:15px}.img-container>button:nth-of-type(2):not(#ngx-fs-btn){bottom:65px}.img-container>button:nth-of-type(3):not(#ngx-fs-btn){bottom:115px}.img-container>button:nth-of-type(4):not(#ngx-fs-btn){bottom:165px}.img-container>button:nth-of-type(5):not(#ngx-fs-btn){bottom:215px}.img-container>button:nth-of-type(6):not(#ngx-fs-btn){bottom:265px}.img-container>button:nth-of-type(7):not(#ngx-fs-btn){bottom:315px}#ngx-fs-btn{top:15px}.nav-button-container{text-align:center;position:absolute;z-index:98;bottom:10px;left:0;right:0}.nav-button-container>button{position:relative;right:0;margin:0 10px}.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}@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')) ], ImageViewerComponent); export { ImageViewerComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWltYWdldmlld2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0B1ZGhzaW4vbmd4LWltYWdlLXZpZXdlci8iLCJzb3VyY2VzIjpbImxpYi9uZ3gtaW1hZ2V2aWV3ZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULEtBQUssRUFDTCxRQUFRLEVBQ1IsTUFBTSxFQUNOLE1BQU0sRUFDTixZQUFZLEVBQ1osWUFBWSxHQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBcUIsV0FBVyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFaEYsTUFBTSxjQUFjLEdBQXNCO0lBQ3hDLFFBQVEsRUFBRSxTQUFTO0lBQ25CLFVBQVUsRUFBRSxHQUFHO0lBQ2Ysd0JBQXdCLEVBQUUsTUFBTTtJQUNoQyxTQUFTLEVBQUUsS0FBSztJQUNoQixlQUFlLEVBQUUsSUFBSTtJQUNyQix1QkFBdUIsRUFBRSxJQUFJO0lBQzdCLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLE9BQU8sRUFBRTtRQUNQLE1BQU0sRUFBRSxJQUFJO1FBQ1osT0FBTyxFQUFFLElBQUk7UUFDYixlQUFlLEVBQUUsSUFBSTtRQUNyQixzQkFBc0IsRUFBRSxJQUFJO1FBQzVCLElBQUksRUFBRSxJQUFJO1FBQ1YsSUFBSSxFQUFFLElBQUk7S0FDWDtJQUNELFFBQVEsRUFBRTtRQUNSLE1BQU0sRUFBRSxZQUFZO1FBQ3BCLE9BQU8sRUFBRSxhQUFhO1FBQ3RCLGVBQWUsRUFBRSxjQUFjO1FBQy9CLHNCQUFzQixFQUFFLFlBQVk7UUFDcEMsSUFBSSxFQUFFLG1CQUFtQjtRQUN6QixJQUFJLEVBQUUsa0JBQWtCO1FBQ3hCLFVBQVUsRUFBRSxrQkFBa0I7S0FDL0I7Q0FDRixDQUFDO0FBT0YsSUFBYSxvQkFBb0IsR0FBakMsTUFBYSxvQkFBb0I7SUFtQy9CLFlBQ3VDLFlBQStCO1FBQS9CLGlCQUFZLEdBQVosWUFBWSxDQUFtQjtRQS9C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UUFBUSxFQUFFLENBQUEsRUFBRSxXQUFBLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQTtHQXBDcEIsb0JBQW9CLENBeUxoQztTQXpMWSxvQkFBb0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIE9uSW5pdCxcbiAgSW5wdXQsXG4gIE9wdGlvbmFsLFxuICBJbmplY3QsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0TGlzdGVuZXIsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSW1hZ2VWaWV3ZXJDb25maWcsIEN1c3RvbUV2ZW50IH0gZnJvbSAnLi9uZ3gtaW1hZ2V2aWV3ZXItY29uZmlnLm1vZGVsJztcblxuY29uc3QgREVGQVVMVF9DT05GSUc6IEltYWdlVmlld2VyQ29uZmlnID0ge1xuICBidG5DbGFzczogJ2RlZmF1bHQnLFxuICB6b29tRmFjdG9yOiAwLjEsXG4gIGNvbnRhaW5lckJhY2tncm91bmRDb2xvcjogJyNjY2MnLFxuICB3aGVlbFpvb206IGZhbHNlLFxuICBhbGxvd0Z1bGxzY3JlZW46IHRydWUsXG4gIGFsbG93S2V5Ym9hcmROYXZpZ2F0aW9uOiB0cnVlLFxuICBhbGlnbkNlbnRlcjogdHJ1ZSxcbiAgYnRuU2hvdzoge1xuICAgIHpvb21JbjogdHJ1ZSxcbiAgICB6b29tT3V0OiB0cnVlLFxuICAgIHJvdGF0ZUNsb2Nrd2lzZTogdHJ1ZSxcbiAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlOiB0cnVlLFxuICAgIG5leHQ6IHRydWUsXG4gICAgcHJldjogdHJ1ZSxcbiAgfSxcbiAgYnRuSWNvbnM6IHtcbiAgICB6b29tSW46ICdmYSBmYS1wbHVzJyxcbiAgICB6b29tT3V0OiAnZmEgZmEtbWludXMnLFxuICAgIHJvdGF0ZUNsb2Nrd2lzZTogJ2ZhIGZhLXJlcGVhdCcsXG4gICAgcm90YXRlQ291bnRlckNsb2Nrd2lzZTogJ2ZhIGZhLXVuZG8nLFxuICAgIG5leHQ6ICdmYSBmYS1hcnJvdy1yaWdodCcsXG4gICAgcHJldjogJ2ZhIGZhLWFycm93LWxlZnQnLFxuICAgIGZ1bGxzY3JlZW46ICdmYSBmYS1hcnJvd3MtYWx0JyxcbiAgfSxcbn07XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1pbWFnZS12aWV3ZXInLFxuICB0ZW1wbGF0ZVVybDogJy4vbmd4LWltYWdldmlld2VyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vbmd4LWltYWdldmlld2VyLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIEltYWdlVmlld2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQElucHV0KClcbiAgc3JjOiBzdHJpbmdbXTtcblxuICBASW5wdXQoKVxuICBpbmRleCA9IDA7XG5cbiAgQElucHV0KClcbiAgY29uZmlnOiBJbWFnZVZpZXdlckNvbmZpZztcblxuICBAT3V0cHV0KClcbiAgaW5kZXhDaGFuZ2U6IEV2ZW50RW1pdHRlcjxudW1iZXI+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoKVxuICBjb25maWdDaGFuZ2U6IEV2ZW50RW1pdHRlcjxJbWFnZVZpZXdlckNvbmZpZz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpXG4gIGN1c3RvbUV2ZW50OiBFdmVudEVtaXR0ZXI8Q3VzdG9tRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHB1YmxpYyBzdHlsZSA9IHtcbiAgICB0cmFuc2Zvcm06ICcnLFxuICAgIG1zVHJhbnNmb3JtOiAnJyxcbiAgICBvVHJhbnNmb3JtOiAnJyxcbiAgICB3ZWJraXRUcmFuc2Zvcm06ICcnLFxuICB9O1xuICBwdWJsaWMgZnVsbHNjcmVlbiA9IGZhbHNlO1xuICBwdWJsaWMgbG9hZGluZyA9IHRydWU7XG4gIHByaXZhdGUgc2NhbGUgPSAxO1xuICBwcml2YXRlIHJvdGF0aW9uID0gMDtcbiAgcHJpdmF0ZSB0cmFuc2xhdGVYID0gMDtcbiAgcHJpdmF0ZSB0cmFuc2xhdGVZID0gMDtcbiAgcHJpdmF0ZSBwcmV2WDogbnVtYmVyO1xuICBwcml2YXRlIHByZXZZOiBudW1iZXI7XG4gIHByaXZhdGUgaG92ZXJlZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoJ2NvbmZpZycpIHB1YmxpYyBtb2R1bGVDb25maWc6IEltYWdlVmlld2VyQ29uZmlnXG4gICkge31cblxuICBuZ09uSW5pdCgpIHtcbiAgICBjb25zdCBtZXJnZWQgPSB0aGlzLm1lcmdlQ29uZmlnKERFRkFVTFRfQ09ORklHLCB0aGlzLm1vZHVsZUNvbmZpZyk7XG4gICAgdGhpcy5jb25maWcgPSB0aGlzLm1lcmdlQ29uZmlnKG1lcmdlZCwgdGhpcy5jb25maWcpO1xuICAgIHRoaXMudHJpZ2dlckNvbmZpZ0JpbmRpbmcoKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXl1cC5BcnJvd1JpZ2h0JywgWyckZXZlbnQnXSlcbiAgbmV4dEltYWdlKGV2ZW50KSB7XG4gICAgaWYgKHRoaXMuY2FuTmF2aWdhdGUoZXZlbnQpICYmIHRoaXMuaW5kZXggPCB0aGlzLnNyYy5sZW5ndGggLSAxKSB7XG4gICAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5pbmRleCsrO1xuICAgICAgdGhpcy50cmlnZ2VySW5kZXhCaW5kaW5nKCk7XG4gICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleXVwLkFycm93TGVmdCcsIFsnJGV2ZW50J10pXG4gIHByZXZJbWFnZShldmVudCkge1xuICAgIGlmICh0aGlzLmNhbk5hdmlnYXRlKGV2ZW50KSAmJiB0aGlzLmluZGV4ID4gMCkge1xuICAgICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuaW5kZXgtLTtcbiAgICAgIHRoaXMudHJpZ2dlckluZGV4QmluZGluZygpO1xuICAgICAgdGhpcy5yZXNldCgpO1xuICAgIH1cbiAgfVxuXG4gIHpvb21JbigpIHtcbiAgICB0aGlzLnNjYWxlICo9IDEgKyB0aGlzLmNvbmZpZy56b29tRmFjdG9yO1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgfVxuXG4gIHpvb21PdXQoKSB7XG4gICAgaWYgKHRoaXMuc2NhbGUgPiB0aGlzLmNvbmZpZy56b29tRmFjdG9yKSB7XG4gICAgICB0aGlzLnNjYWxlIC89IDEgKyB0aGlzLmNvbmZpZy56b29tRmFjdG9yO1xuICAgIH1cbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICBzY3JvbGxab29tKGV2dCkge1xuICAgIGlmICh0aGlzLmNvbmZpZy53aGVlbFpvb20pIHtcbiAgICAgIGV2dC5kZWx0YVkgPiAwID8gdGhpcy56b29tT3V0KCkgOiB0aGlzLnpvb21JbigpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJvdGF0ZUNsb2Nrd2lzZSgpIHtcbiAgICB0aGlzLnJvdGF0aW9uICs9IDkwO1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgfVxuXG4gIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKSB7XG4gICAgdGhpcy5yb3RhdGlvbiAtPSA5MDtcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICBvbkxvYWQoKSB7XG4gICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gIH1cblxuICBvbkxvYWRTdGFydCgpIHtcbiAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuICB9XG5cbiAgb25EcmFnT3ZlcihldnQpIHtcbiAgICB0aGlzLnRyYW5zbGF0ZVggKz0gZXZ0LmNsaWVudFggLSB0aGlzLnByZXZYO1xuICAgIHRoaXMudHJhbnNsYXRlWSArPSBldnQuY2xpZW50WSAtIHRoaXMucHJldlk7XG4gICAgdGhpcy5wcmV2WCA9IGV2dC5jbGllbnRYO1xuICAgIHRoaXMucHJldlkgPSBldnQuY2xpZW50WTtcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICBvbkRyYWdTdGFydChldnQpIHtcbiAgICBpZiAoZXZ0LmRhdGFUcmFuc2ZlciAmJiBldnQuZGF0YVRyYW5zZmVyLnNldERyYWdJbWFnZSkge1xuICAgICAgZXZ0LmRhdGFUcmFuc2Zlci5zZXREcmFnSW1hZ2UoZXZ0LnRhcmdldC5uZXh0RWxlbWVudFNpYmxpbmcsIDAsIDApO1xuICAgIH1cbiAgICB0aGlzLnByZXZYID0gZXZ0LmNsaWVudFg7XG4gICAgdGhpcy5wcmV2WSA9IGV2dC5jbGllbnRZO1xuICB9XG5cbiAgdG9nZ2xlRnVsbHNjcmVlbigpIHtcbiAgICB0aGlzLmZ1bGxzY3JlZW4gPSAhdGhpcy5mdWxsc2NyZWVuO1xuICAgIGlmICghdGhpcy5mdWxsc2NyZWVuKSB7XG4gICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuICB9XG5cbiAgdHJpZ2dlckluZGV4QmluZGluZygpIHtcbiAgICB0aGlzLmluZGV4Q2hhbmdlLmVtaXQodGhpcy5pbmRleCk7XG4gIH1cblxuICB0cmlnZ2VyQ29uZmlnQmluZGluZygpIHtcbiAgICB0aGlzLmNvbmZpZ0NoYW5nZS5uZXh0KHRoaXMuY29uZmlnKTtcbiAgfVxuXG4gIGZpcmVDdXN0b21FdmVudChuYW1lLCBpbWFnZUluZGV4KSB7XG4gICAgdGhpcy5jdXN0b21FdmVudC5lbWl0KG5ldyBDdXN0b21FdmVudChuYW1lLCBpbWFnZUluZGV4KSk7XG4gIH1cblxuICByZXNldCgpIHtcbiAgICB0aGlzLnNjYWxlID0gMTtcbiAgICB0aGlzLnJvdGF0aW9uID0gMDtcbiAgICB0aGlzLnRyYW5zbGF0ZVggPSAwO1xuICAgIHRoaXMudHJhbnNsYXRlWSA9IDA7XG4gICAgdGhpcy51cGRhdGVTdHlsZSgpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2VvdmVyJylcbiAgb25Nb3VzZU92ZXIoKSB7XG4gICAgdGhpcy5ob3ZlcmVkID0gdHJ1ZTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlbGVhdmUnKVxuICBvbk1vdXNlTGVhdmUoKSB7XG4gICAgdGhpcy5ob3ZlcmVkID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGNhbk5hdmlnYXRlKGV2ZW50OiBhbnkpIHtcbiAgICByZXR1cm4gKFxuICAgICAgZXZlbnQgPT0gbnVsbCB8fCAodGhpcy5jb25maWcuYWxsb3dLZXlib2FyZE5hdmlnYXRpb24gJiYgdGhpcy5ob3ZlcmVkKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVN0eWxlKCkge1xuICAgIHRoaXMuc3R5bGUudHJhbnNmb3JtID0gYHRyYW5zbGF0ZSgke3RoaXMudHJhbnNsYXRlWH1weCwgJHt0aGlzLnRyYW5zbGF0ZVl9cHgpIHJvdGF0ZSgke3RoaXMucm90YXRpb259ZGVnKSBzY2FsZSgke3RoaXMuc2NhbGV9KWA7XG4gICAgdGhpcy5zdHlsZS5tc1RyYW5zZm9ybSA9IHRoaXMuc3R5bGUudHJhbnNmb3JtO1xuICAgIHRoaXMuc3R5bGUud2Via2l0VHJhbnNmb3JtID0gdGhpcy5zdHlsZS50cmFuc2Zvcm07XG4gICAgdGhpcy5zdHlsZS5vVHJhbnNmb3JtID0gdGhpcy5zdHlsZS50cmFuc2Zvcm07XG4gIH1cblxuICBwcml2YXRlIG1lcmdlQ29uZmlnKFxuICAgIGRlZmF1bHRWYWx1ZXM6IEltYWdlVmlld2VyQ29uZmlnLFxuICAgIG92ZXJyaWRlVmFsdWVzOiBJbWFnZVZpZXdlckNvbmZpZ1xuICApOiBJbWFnZVZpZXdlckNvbmZpZyB7XG4gICAgbGV0IHJlc3VsdDogSW1hZ2VWaWV3ZXJDb25maWcgPSB7IC4uLmRlZmF1bHRWYWx1ZXMgfTtcbiAgICBpZiAob3ZlcnJpZGVWYWx1ZXMpIHtcbiAgICAgIHJlc3VsdCA9IHsgLi4uZGVmYXVsdFZhbHVlcywgLi4ub3ZlcnJpZGVWYWx1ZXMgfTtcblxuICAgICAgaWYgKG92ZXJyaWRlVmFsdWVzLmJ0bkljb25zKSB7XG4gICAgICAgIHJlc3VsdC5idG5JY29ucyA9IHtcbiAgICAgICAgICAuLi5kZWZhdWx0VmFsdWVzLmJ0bkljb25zLFxuICAgICAgICAgIC4uLm92ZXJyaWRlVmFsdWVzLmJ0bkljb25zLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG4iXX0=