UNPKG

@udhsin/ngx-image-viewer

Version:

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

207 lines 26.9 kB
import { __assign, __decorate, __param } from "tslib"; import { Component, Input, Optional, Inject, Output, EventEmitter, HostListener, } from '@angular/core'; import { CustomEvent } from './ngx-imageviewer-config.model'; var 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', }, }; var ImageViewerComponent = /** @class */ (function () { function ImageViewerComponent(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; } ImageViewerComponent.prototype.ngOnInit = function () { var merged = this.mergeConfig(DEFAULT_CONFIG, this.moduleConfig); this.config = this.mergeConfig(merged, this.config); this.triggerConfigBinding(); }; ImageViewerComponent.prototype.nextImage = function (event) { if (this.canNavigate(event) && this.index < this.src.length - 1) { this.loading = true; this.index++; this.triggerIndexBinding(); this.reset(); } }; ImageViewerComponent.prototype.prevImage = function (event) { if (this.canNavigate(event) && this.index > 0) { this.loading = true; this.index--; this.triggerIndexBinding(); this.reset(); } }; ImageViewerComponent.prototype.zoomIn = function () { this.scale *= 1 + this.config.zoomFactor; this.updateStyle(); }; ImageViewerComponent.prototype.zoomOut = function () { if (this.scale > this.config.zoomFactor) { this.scale /= 1 + this.config.zoomFactor; } this.updateStyle(); }; ImageViewerComponent.prototype.scrollZoom = function (evt) { if (this.config.wheelZoom) { evt.deltaY > 0 ? this.zoomOut() : this.zoomIn(); return false; } }; ImageViewerComponent.prototype.rotateClockwise = function () { this.rotation += 90; this.updateStyle(); }; ImageViewerComponent.prototype.rotateCounterClockwise = function () { this.rotation -= 90; this.updateStyle(); }; ImageViewerComponent.prototype.onLoad = function () { this.loading = false; }; ImageViewerComponent.prototype.onLoadStart = function () { this.loading = true; }; ImageViewerComponent.prototype.onDragOver = function (evt) { this.translateX += evt.clientX - this.prevX; this.translateY += evt.clientY - this.prevY; this.prevX = evt.clientX; this.prevY = evt.clientY; this.updateStyle(); }; ImageViewerComponent.prototype.onDragStart = function (evt) { if (evt.dataTransfer && evt.dataTransfer.setDragImage) { evt.dataTransfer.setDragImage(evt.target.nextElementSibling, 0, 0); } this.prevX = evt.clientX; this.prevY = evt.clientY; }; ImageViewerComponent.prototype.toggleFullscreen = function () { this.fullscreen = !this.fullscreen; if (!this.fullscreen) { this.reset(); } }; ImageViewerComponent.prototype.triggerIndexBinding = function () { this.indexChange.emit(this.index); }; ImageViewerComponent.prototype.triggerConfigBinding = function () { this.configChange.next(this.config); }; ImageViewerComponent.prototype.fireCustomEvent = function (name, imageIndex) { this.customEvent.emit(new CustomEvent(name, imageIndex)); }; ImageViewerComponent.prototype.reset = function () { this.scale = 1; this.rotation = 0; this.translateX = 0; this.translateY = 0; this.updateStyle(); }; ImageViewerComponent.prototype.onMouseOver = function () { this.hovered = true; }; ImageViewerComponent.prototype.onMouseLeave = function () { this.hovered = false; }; ImageViewerComponent.prototype.canNavigate = function (event) { return (event == null || (this.config.allowKeyboardNavigation && this.hovered)); }; ImageViewerComponent.prototype.updateStyle = function () { 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; }; ImageViewerComponent.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; }; ImageViewerComponent.ctorParameters = function () { return [ { 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); return ImageViewerComponent; }()); export { ImageViewerComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWltYWdldmlld2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0B1ZGhzaW4vbmd4LWltYWdlLXZpZXdlci8iLCJzb3VyY2VzIjpbImxpYi9uZ3gtaW1hZ2V2aWV3ZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULEtBQUssRUFDTCxRQUFRLEVBQ1IsTUFBTSxFQUNOLE1BQU0sRUFDTixZQUFZLEVBQ1osWUFBWSxHQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBcUIsV0FBVyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFaEYsSUFBTSxjQUFjLEdBQXNCO0lBQ3hDLFFBQVEsRUFBRSxTQUFTO0lBQ25CLFVBQVUsRUFBRSxHQUFHO0lBQ2Ysd0JBQXdCLEVBQUUsTUFBTTtJQUNoQyxTQUFTLEVBQUUsS0FBSztJQUNoQixlQUFlLEVBQUUsSUFBSTtJQUNyQix1QkFBdUIsRUFBRSxJQUFJO0lBQzdCLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLE9BQU8sRUFBRTtRQUNQLE1BQU0sRUFBRSxJQUFJO1FBQ1osT0FBTyxFQUFFLElBQUk7UUFDYixlQUFlLEVBQUUsSUFBSTtRQUNyQixzQkFBc0IsRUFBRSxJQUFJO1FBQzVCLElBQUksRUFBRSxJQUFJO1FBQ1YsSUFBSSxFQUFFLElBQUk7S0FDWDtJQUNELFFBQVEsRUFBRTtRQUNSLE1BQU0sRUFBRSxZQUFZO1FBQ3BCLE9BQU8sRUFBRSxhQUFhO1FBQ3RCLGVBQWUsRUFBRSxjQUFjO1FBQy9CLHNCQUFzQixFQUFFLFlBQVk7UUFDcEMsSUFBSSxFQUFFLG1CQUFtQjtRQUN6QixJQUFJLEVBQUUsa0JBQWtCO1FBQ3hCLFVBQVUsRUFBRSxrQkFBa0I7S0FDL0I7Q0FDRixDQUFDO0FBT0Y7SUFtQ0UsOEJBQ3VDLFlBQStCO1FBQS9CLGlCQUFZLEdBQVosWUFBWSxDQUFtQjtRQS9CdEUsVUFBSyxHQUFHLENBQUMsQ0FBQztRQU1WLGdC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REFHMUI7SUF6SlUsb0JBQW9CO1FBTGhDLFNBQVMsQ0FBQztZQUNULFFBQVEsRUFBRSxrQkFBa0I7WUFDNUIsMnFGQUErQzs7U0FFaEQsQ0FBQztRQXFDRyxXQUFBLFFBQVEsRUFBRSxDQUFBLEVBQUUsV0FBQSxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7T0FwQ3BCLG9CQUFvQixDQXlMaEM7SUFBRCwyQkFBQztDQUFBLEFBekxELElBeUxDO1NBekxZLG9CQUFvQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgT25Jbml0LFxuICBJbnB1dCxcbiAgT3B0aW9uYWwsXG4gIEluamVjdCxcbiAgT3V0cHV0LFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJbWFnZVZpZXdlckNvbmZpZywgQ3VzdG9tRXZlbnQgfSBmcm9tICcuL25neC1pbWFnZXZpZXdlci1jb25maWcubW9kZWwnO1xuXG5jb25zdCBERUZBVUxUX0NPTkZJRzogSW1hZ2VWaWV3ZXJDb25maWcgPSB7XG4gIGJ0bkNsYXNzOiAnZGVmYXVsdCcsXG4gIHpvb21GYWN0b3I6IDAuMSxcbiAgY29udGFpbmVyQmFja2dyb3VuZENvbG9yOiAnI2NjYycsXG4gIHdoZWVsWm9vbTogZmFsc2UsXG4gIGFsbG93RnVsbHNjcmVlbjogdHJ1ZSxcbiAgYWxsb3dLZXlib2FyZE5hdmlnYXRpb246IHRydWUsXG4gIGFsaWduQ2VudGVyOiB0cnVlLFxuICBidG5TaG93OiB7XG4gICAgem9vbUluOiB0cnVlLFxuICAgIHpvb21PdXQ6IHRydWUsXG4gICAgcm90YXRlQ2xvY2t3aXNlOiB0cnVlLFxuICAgIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2U6IHRydWUsXG4gICAgbmV4dDogdHJ1ZSxcbiAgICBwcmV2OiB0cnVlLFxuICB9LFxuICBidG5JY29uczoge1xuICAgIHpvb21JbjogJ2ZhIGZhLXBsdXMnLFxuICAgIHpvb21PdXQ6ICdmYSBmYS1taW51cycsXG4gICAgcm90YXRlQ2xvY2t3aXNlOiAnZmEgZmEtcmVwZWF0JyxcbiAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlOiAnZmEgZmEtdW5kbycsXG4gICAgbmV4dDogJ2ZhIGZhLWFycm93LXJpZ2h0JyxcbiAgICBwcmV2OiAnZmEgZmEtYXJyb3ctbGVmdCcsXG4gICAgZnVsbHNjcmVlbjogJ2ZhIGZhLWFycm93cy1hbHQnLFxuICB9LFxufTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWltYWdlLXZpZXdlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9uZ3gtaW1hZ2V2aWV3ZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9uZ3gtaW1hZ2V2aWV3ZXIuY29tcG9uZW50LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgSW1hZ2VWaWV3ZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBASW5wdXQoKVxuICBzcmM6IHN0cmluZ1tdO1xuXG4gIEBJbnB1dCgpXG4gIGluZGV4ID0gMDtcblxuICBASW5wdXQoKVxuICBjb25maWc6IEltYWdlVmlld2VyQ29uZmlnO1xuXG4gIEBPdXRwdXQoKVxuICBpbmRleENoYW5nZTogRXZlbnRFbWl0dGVyPG51bWJlcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpXG4gIGNvbmZpZ0NoYW5nZTogRXZlbnRFbWl0dGVyPEltYWdlVmlld2VyQ29uZmlnPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KClcbiAgY3VzdG9tRXZlbnQ6IEV2ZW50RW1pdHRlcjxDdXN0b21FdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHVibGljIHN0eWxlID0ge1xuICAgIHRyYW5zZm9ybTogJycsXG4gICAgbXNUcmFuc2Zvcm06ICcnLFxuICAgIG9UcmFuc2Zvcm06ICcnLFxuICAgIHdlYmtpdFRyYW5zZm9ybTogJycsXG4gIH07XG4gIHB1YmxpYyBmdWxsc2NyZWVuID0gZmFsc2U7XG4gIHB1YmxpYyBsb2FkaW5nID0gdHJ1ZTtcbiAgcHJpdmF0ZSBzY2FsZSA9IDE7XG4gIHByaXZhdGUgcm90YXRpb24gPSAwO1xuICBwcml2YXRlIHRyYW5zbGF0ZVggPSAwO1xuICBwcml2YXRlIHRyYW5zbGF0ZVkgPSAwO1xuICBwcml2YXRlIHByZXZYOiBudW1iZXI7XG4gIHByaXZhdGUgcHJldlk6IG51bWJlcjtcbiAgcHJpdmF0ZSBob3ZlcmVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdCgnY29uZmlnJykgcHVibGljIG1vZHVsZUNvbmZpZzogSW1hZ2VWaWV3ZXJDb25maWdcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCkge1xuICAgIGNvbnN0IG1lcmdlZCA9IHRoaXMubWVyZ2VDb25maWcoREVGQVVMVF9DT05GSUcsIHRoaXMubW9kdWxlQ29uZmlnKTtcbiAgICB0aGlzLmNvbmZpZyA9IHRoaXMubWVyZ2VDb25maWcobWVyZ2VkLCB0aGlzLmNvbmZpZyk7XG4gICAgdGhpcy50cmlnZ2VyQ29uZmlnQmluZGluZygpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleXVwLkFycm93UmlnaHQnLCBbJyRldmVudCddKVxuICBuZXh0SW1hZ2UoZXZlbnQpIHtcbiAgICBpZiAodGhpcy5jYW5OYXZpZ2F0ZShldmVudCkgJiYgdGhpcy5pbmRleCA8IHRoaXMuc3JjLmxlbmd0aCAtIDEpIHtcbiAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG4gICAgICB0aGlzLmluZGV4Kys7XG4gICAgICB0aGlzLnRyaWdnZXJJbmRleEJpbmRpbmcoKTtcbiAgICAgIHRoaXMucmVzZXQoKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5dXAuQXJyb3dMZWZ0JywgWyckZXZlbnQnXSlcbiAgcHJldkltYWdlKGV2ZW50KSB7XG4gICAgaWYgKHRoaXMuY2FuTmF2aWdhdGUoZXZlbnQpICYmIHRoaXMuaW5kZXggPiAwKSB7XG4gICAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5pbmRleC0tO1xuICAgICAgdGhpcy50cmlnZ2VySW5kZXhCaW5kaW5nKCk7XG4gICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuICB9XG5cbiAgem9vbUluKCkge1xuICAgIHRoaXMuc2NhbGUgKj0gMSArIHRoaXMuY29uZmlnLnpvb21GYWN0b3I7XG4gICAgdGhpcy51cGRhdGVTdHlsZSgpO1xuICB9XG5cbiAgem9vbU91dCgpIHtcbiAgICBpZiAodGhpcy5zY2FsZSA+IHRoaXMuY29uZmlnLnpvb21GYWN0b3IpIHtcbiAgICAgIHRoaXMuc2NhbGUgLz0gMSArIHRoaXMuY29uZmlnLnpvb21GYWN0b3I7XG4gICAgfVxuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgfVxuXG4gIHNjcm9sbFpvb20oZXZ0KSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLndoZWVsWm9vbSkge1xuICAgICAgZXZ0LmRlbHRhWSA+IDAgPyB0aGlzLnpvb21PdXQoKSA6IHRoaXMuem9vbUluKCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcm90YXRlQ2xvY2t3aXNlKCkge1xuICAgIHRoaXMucm90YXRpb24gKz0gOTA7XG4gICAgdGhpcy51cGRhdGVTdHlsZSgpO1xuICB9XG5cbiAgcm90YXRlQ291bnRlckNsb2Nrd2lzZSgpIHtcbiAgICB0aGlzLnJvdGF0aW9uIC09IDkwO1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgfVxuXG4gIG9uTG9hZCgpIHtcbiAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgfVxuXG4gIG9uTG9hZFN0YXJ0KCkge1xuICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG4gIH1cblxuICBvbkRyYWdPdmVyKGV2dCkge1xuICAgIHRoaXMudHJhbnNsYXRlWCArPSBldnQuY2xpZW50WCAtIHRoaXMucHJldlg7XG4gICAgdGhpcy50cmFuc2xhdGVZICs9IGV2dC5jbGllbnRZIC0gdGhpcy5wcmV2WTtcbiAgICB0aGlzLnByZXZYID0gZXZ0LmNsaWVudFg7XG4gICAgdGhpcy5wcmV2WSA9IGV2dC5jbGllbnRZO1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgfVxuXG4gIG9uRHJhZ1N0YXJ0KGV2dCkge1xuICAgIGlmIChldnQuZGF0YVRyYW5zZmVyICYmIGV2dC5kYXRhVHJhbnNmZXIuc2V0RHJhZ0ltYWdlKSB7XG4gICAgICBldnQuZGF0YVRyYW5zZmVyLnNldERyYWdJbWFnZShldnQudGFyZ2V0Lm5leHRFbGVtZW50U2libGluZywgMCwgMCk7XG4gICAgfVxuICAgIHRoaXMucHJldlggPSBldnQuY2xpZW50WDtcbiAgICB0aGlzLnByZXZZID0gZXZ0LmNsaWVudFk7XG4gIH1cblxuICB0b2dnbGVGdWxsc2NyZWVuKCkge1xuICAgIHRoaXMuZnVsbHNjcmVlbiA9ICF0aGlzLmZ1bGxzY3JlZW47XG4gICAgaWYgKCF0aGlzLmZ1bGxzY3JlZW4pIHtcbiAgICAgIHRoaXMucmVzZXQoKTtcbiAgICB9XG4gIH1cblxuICB0cmlnZ2VySW5kZXhCaW5kaW5nKCkge1xuICAgIHRoaXMuaW5kZXhDaGFuZ2UuZW1pdCh0aGlzLmluZGV4KTtcbiAgfVxuXG4gIHRyaWdnZXJDb25maWdCaW5kaW5nKCkge1xuICAgIHRoaXMuY29uZmlnQ2hhbmdlLm5leHQodGhpcy5jb25maWcpO1xuICB9XG5cbiAgZmlyZUN1c3RvbUV2ZW50KG5hbWUsIGltYWdlSW5kZXgpIHtcbiAgICB0aGlzLmN1c3RvbUV2ZW50LmVtaXQobmV3IEN1c3RvbUV2ZW50KG5hbWUsIGltYWdlSW5kZXgpKTtcbiAgfVxuXG4gIHJlc2V0KCkge1xuICAgIHRoaXMuc2NhbGUgPSAxO1xuICAgIHRoaXMucm90YXRpb24gPSAwO1xuICAgIHRoaXMudHJhbnNsYXRlWCA9IDA7XG4gICAgdGhpcy50cmFuc2xhdGVZID0gMDtcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdtb3VzZW92ZXInKVxuICBvbk1vdXNlT3ZlcigpIHtcbiAgICB0aGlzLmhvdmVyZWQgPSB0cnVlO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScpXG4gIG9uTW91c2VMZWF2ZSgpIHtcbiAgICB0aGlzLmhvdmVyZWQgPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgY2FuTmF2aWdhdGUoZXZlbnQ6IGFueSkge1xuICAgIHJldHVybiAoXG4gICAgICBldmVudCA9PSBudWxsIHx8ICh0aGlzLmNvbmZpZy5hbGxvd0tleWJvYXJkTmF2aWdhdGlvbiAmJiB0aGlzLmhvdmVyZWQpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlU3R5bGUoKSB7XG4gICAgdGhpcy5zdHlsZS50cmFuc2Zvcm0gPSBgdHJhbnNsYXRlKCR7dGhpcy50cmFuc2xhdGVYfXB4LCAke3RoaXMudHJhbnNsYXRlWX1weCkgcm90YXRlKCR7dGhpcy5yb3RhdGlvbn1kZWcpIHNjYWxlKCR7dGhpcy5zY2FsZX0pYDtcbiAgICB0aGlzLnN0eWxlLm1zVHJhbnNmb3JtID0gdGhpcy5zdHlsZS50cmFuc2Zvcm07XG4gICAgdGhpcy5zdHlsZS53ZWJraXRUcmFuc2Zvcm0gPSB0aGlzLnN0eWxlLnRyYW5zZm9ybTtcbiAgICB0aGlzLnN0eWxlLm9UcmFuc2Zvcm0gPSB0aGlzLnN0eWxlLnRyYW5zZm9ybTtcbiAgfVxuXG4gIHByaXZhdGUgbWVyZ2VDb25maWcoXG4gICAgZGVmYXVsdFZhbHVlczogSW1hZ2VWaWV3ZXJDb25maWcsXG4gICAgb3ZlcnJpZGVWYWx1ZXM6IEltYWdlVmlld2VyQ29uZmlnXG4gICk6IEltYWdlVmlld2VyQ29uZmlnIHtcbiAgICBsZXQgcmVzdWx0OiBJbWFnZVZpZXdlckNvbmZpZyA9IHsgLi4uZGVmYXVsdFZhbHVlcyB9O1xuICAgIGlmIChvdmVycmlkZVZhbHVlcykge1xuICAgICAgcmVzdWx0ID0geyAuLi5kZWZhdWx0VmFsdWVzLCAuLi5vdmVycmlkZVZhbHVlcyB9O1xuXG4gICAgICBpZiAob3ZlcnJpZGVWYWx1ZXMuYnRuSWNvbnMpIHtcbiAgICAgICAgcmVzdWx0LmJ0bkljb25zID0ge1xuICAgICAgICAgIC4uLmRlZmF1bHRWYWx1ZXMuYnRuSWNvbnMsXG4gICAgICAgICAgLi4ub3ZlcnJpZGVWYWx1ZXMuYnRuSWNvbnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cbiJdfQ==