ngx-img-zoom-viewer
Version:
The NGX IMG Zoom Viewer is a Angular library that can help to create a magnified preview of any image in any kind of angular app
210 lines (206 loc) • 34.8 kB
JavaScript
import { DOCUMENT } from '@angular/common';
import { Component, HostListener, Input, Inject, } from '@angular/core';
import * as i0 from "@angular/core";
export class NGXImgZoomViewerComponent {
constructor(el, renderer, document) {
this.el = el;
this.renderer = renderer;
this.providedPreviewBox = { height: 350, width: 350 };
this.defaultConfigs = {
imgHeight: 500,
megnification: 2.5,
priviewBoxSize: {
height: 350,
width: 350,
},
};
this.cursorSize = { height: 0, width: 0 };
this._src = '';
this.cursorPosition = { x: 0, y: 0 };
this.host = this.renderer.createElement('div');
this.document = document;
this.renderer.addClass(this.host, 'image_container');
this.renderer.appendChild(el.nativeElement, this.host); // assigning host
}
set src(srcValue) {
if (typeof srcValue === 'string') {
this._src = srcValue;
this.createImage();
}
else {
console.error('src must be of type string, current type found ' + typeof srcValue);
}
}
ngOnChanges(changes) {
this.defaultConfigs.imgHeight =
this.config?.imgHeight ?? this.defaultConfigs.imgHeight;
this.defaultConfigs.megnification =
this.config?.megnification ?? this.defaultConfigs.megnification;
this.defaultConfigs.priviewBoxSize.height =
this.config?.priviewBoxSize?.height ??
this.defaultConfigs.priviewBoxSize.height;
if (this.defaultConfigs.priviewBoxSize.height + 20 > window.innerHeight) {
this.defaultConfigs.priviewBoxSize.height = window.innerHeight - 20;
}
this.defaultConfigs.priviewBoxSize.width =
this.defaultConfigs.priviewBoxSize.height;
this.providedPreviewBox = { ...this.defaultConfigs.priviewBoxSize };
this.createImage();
}
ngOnInit() {
if (!this._src)
console.error('unable to read src attribute');
}
onMouseLeave(e) {
if (this.cursorSize.width < 50 && this.cursorSize.height > 50)
return;
this.renderer.removeChild(this.host, this.cursor);
this.renderer.removeChild(this.document, this.img_preview);
}
onMouseEnter(e) {
this.checkwidth();
if (this.cursorSize.width < 50 && this.cursorSize.height > 50)
return;
if (this.host.children.length > 1) {
this.onMouseLeave(e);
}
if (this.document.getElementById('ngx-img-zoom-viewer')) {
this.renderer.removeChild(this.document, this.document.getElementById('ngx-img-zoom-viewer'));
this.renderer.removeChild(this.document, this.document.getElementById('ngx-img-zoom-cursor'));
}
this.cursor = this.renderer.createElement('div');
this.renderer.addClass(this.cursor, 'cursor');
this.renderer.setStyle(this.cursor, `height`, `${this.cursorSize?.height}px`);
this.renderer.setStyle(this.cursor, `width`, `${this.cursorSize?.width}px`);
this.renderer.setAttribute(this.cursor, 'id', 'ngx-img-zoom-cursor');
this.renderer.appendChild(this.host, this.cursor);
this.setCursorPosition(e);
this.img_preview = this.renderer.createElement('div');
this.renderer.addClass(this.img_preview, 'img_preview');
this.renderer.setStyle(this.img_preview, 'height', `${this.defaultConfigs.priviewBoxSize.height}px`);
this.renderer.setStyle(this.img_preview, 'width', `${this.defaultConfigs.priviewBoxSize.width}px`);
this.renderer.setStyle(this.img_preview, 'left', `${window.innerWidth - 10 - this.defaultConfigs.priviewBoxSize.width}px`);
this.renderer.setAttribute(this.img_preview, 'id', 'ngx-img-zoom-viewer');
this.renderer.appendChild(this.host.ownerDocument.lastChild?.lastChild, this.img_preview);
}
onMouseMove(e) {
if (this.cursorSize.width < 50 && this.cursorSize.height > 50)
return;
this.setCursorPosition(e);
this.setImgPreview(e);
}
setCursorPosition(e) {
/* handling Left & top position for cursor box */
const imagex = this.image.getBoundingClientRect().x;
const imagey = this.image.getBoundingClientRect().y;
let cursorPosition = {
x: e.pageX - this.cursorSize?.width / 2 - imagex >= 0 // checking if cursor box left is less then 0
? e.pageX - this.cursorSize?.width / 2 - imagex
: 0,
y: e.pageY - this.cursorSize?.height / 2 - imagey >= 0 // checking if cursor box top is less then 0
? e.pageY - this.cursorSize?.height / 2 - imagey
: 0, // making sure if it is then only take 0 not negative value
};
/* handling bottom & right position for cursor box */
if (cursorPosition.x + this.cursorSize?.width > this.image.offsetWidth) {
// checking if cursor left + cursor width is greater then image width
// making sure that any single pixel of cursor box can't go out from image respective on width
cursorPosition.x = this.image.offsetWidth - this.cursorSize?.width;
}
if (cursorPosition.y + this.cursorSize?.height > this.image.offsetHeight) {
// making sure that any single pixel of cursor box can't go out from image respective on height
cursorPosition.y = this.image.offsetHeight - this.cursorSize?.height;
}
/* setting final value */
this.renderer.setStyle(this.cursor, 'top', `${cursorPosition.y}px`); // setting cursor box position for y axis
this.renderer.setStyle(this.cursor, 'left', `${cursorPosition.x}px`); // setting cursor box position for x axis
this.cursorPosition = cursorPosition; // saving data to global variable
}
setImgPreview(e) {
const zoomedImage = this.renderer.createElement('img'); // created new local image element
this.renderer.setAttribute(zoomedImage, 'src', this._src); // setting src for local image element
this.renderer.setStyle(zoomedImage, 'height', `${this.image.offsetHeight * this.defaultConfigs.megnification}px`); // changed zoomed image height based on real image
this.renderer.setStyle(zoomedImage, 'width', `${this.image.offsetWidth * this.defaultConfigs.megnification}px`); // changed zoomed image width based on real image
this.renderer.setStyle(zoomedImage, 'top', `-${this.cursorPosition.y * this.defaultConfigs.megnification}px`); // changed zoomed image position based on cursor position
this.renderer.setStyle(zoomedImage, 'left', `-${this.cursorPosition.x * this.defaultConfigs.megnification}px`); // changed zoomed image position based on cursor position
this.img_preview.innerHTML = '';
this.renderer.appendChild(this.img_preview, zoomedImage); // added image into img_preview box
}
createImage() {
this.host.innerHTML = '';
this.image = this.renderer.createElement('img');
this.renderer.setAttribute(this.image, 'src', this._src);
this.renderer.addClass(this.image, 'main_image');
this.renderer.setStyle(this.image, 'max-height', this.defaultConfigs.imgHeight + 'px');
this.renderer.appendChild(this.host, this.image);
}
checkwidth() {
this.defaultConfigs.priviewBoxSize.width = this.providedPreviewBox.width;
const def = this.image.getBoundingClientRect().x +
this.image.width +
this.defaultConfigs.priviewBoxSize.width +
20 -
window.innerWidth;
if (def >= 0) {
this.defaultConfigs.priviewBoxSize.width =
this.defaultConfigs.priviewBoxSize.width - def - 30;
}
this.cursorSize.height =
this.defaultConfigs.priviewBoxSize.height /
this.defaultConfigs.megnification;
this.cursorSize.width =
this.defaultConfigs.priviewBoxSize.width /
this.defaultConfigs.megnification;
}
}
NGXImgZoomViewerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: NGXImgZoomViewerComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component });
NGXImgZoomViewerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.3", type: NGXImgZoomViewerComponent, selector: "ngx-img-zoom-viewer", inputs: { config: "config", src: "src" }, host: { listeners: { "mouseleave": "onMouseLeave($event)", "mouseenter": "onMouseEnter($event)", "mousemove": "onMouseMove($event)" } }, usesOnChanges: true, ngImport: i0, template: ``, isInline: true, styles: [".image_container{position:relative;display:inline-block}.image_container img{width:100%}.cursor{position:absolute;background-color:#ffffff80}.img_preview{position:fixed;z-index:1000;top:10px;right:10px;overflow:hidden}.img_preview img{position:absolute}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: NGXImgZoomViewerComponent, decorators: [{
type: Component,
args: [{
selector: 'ngx-img-zoom-viewer',
template: ``,
styles: [
`
.image_container {
position: relative;
display: inline-block;
}
.image_container img {
width: 100%;
}
.cursor {
position: absolute;
background-color: rgba(255, 255, 255, 0.5);
}
.img_preview {
position: fixed;
z-index: 1000;
top: 10px;
right: 10px;
overflow: hidden;
}
.img_preview img {
position: absolute;
}
`,
],
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }]; }, propDecorators: { config: [{
type: Input
}], src: [{
type: Input
}], onMouseLeave: [{
type: HostListener,
args: ['mouseleave', ['$event']]
}], onMouseEnter: [{
type: HostListener,
args: ['mouseenter', ['$event']]
}], onMouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWltZy16b29tLXZpZXdlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtaW1nLXpvb20tdmlld2VyL3NyYy9saWIvbmd4LWltZy16b29tLXZpZXdlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFDTCxTQUFTLEVBRVQsWUFBWSxFQUNaLEtBQUssRUFLTCxNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7O0FBMkN2QixNQUFNLE9BQU8seUJBQXlCO0lBMkNwQyxZQUNVLEVBQWMsRUFDZCxRQUFtQixFQUNULFFBQWtCO1FBRjVCLE9BQUUsR0FBRixFQUFFLENBQVk7UUFDZCxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBM0JyQix1QkFBa0IsR0FHdEIsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUV4QixtQkFBYyxHQUFHO1lBQ3ZCLFNBQVMsRUFBRSxHQUFHO1lBQ2QsYUFBYSxFQUFFLEdBQUc7WUFDbEIsY0FBYyxFQUFFO2dCQUNkLE1BQU0sRUFBRSxHQUFHO2dCQUNYLEtBQUssRUFBRSxHQUFHO2FBQ1g7U0FDRixDQUFDO1FBSU0sZUFBVSxHQUdkLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFFcEIsU0FBSSxHQUFXLEVBQUUsQ0FBQztRQUVsQixtQkFBYyxHQUE2QixFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBT2hFLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDL0MsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFD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c0JBRG5CLFlBQVk7dUJBQUMsWUFBWSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQVE5QixZQUFZO3NCQURuQixZQUFZO3VCQUFDLFlBQVksRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFxRDlCLFdBQVc7c0JBRGxCLFlBQVk7dUJBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBIb3N0TGlzdGVuZXIsXG4gIElucHV0LFxuICBPbkluaXQsXG4gIFJlbmRlcmVyMixcbiAgT25DaGFuZ2VzLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBJbmplY3QsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5leHBvcnQgaW50ZXJmYWNlIGltZ1pvb21WaWV3ZXJDb25maWcge1xuICBpbWdIZWlnaHQ/OiBudW1iZXI7XG4gIG1lZ25pZmljYXRpb24/OiBudW1iZXI7XG4gIHByaXZpZXdCb3hTaXplPzoge1xuICAgIGhlaWdodD86IG51bWJlcjtcbiAgfTtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWltZy16b29tLXZpZXdlcicsXG4gIHRlbXBsYXRlOiBgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgLmltYWdlX2NvbnRhaW5lciB7XG4gICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICAgICAgfVxuXG4gICAgICAuaW1hZ2VfY29udGFpbmVyIGltZyB7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgfVxuXG4gICAgICAuY3Vyc29yIHtcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSk7XG4gICAgICB9XG5cbiAgICAgIC5pbWdfcHJldmlldyB7XG4gICAgICAgIHBvc2l0aW9uOiBmaXhlZDtcbiAgICAgICAgei1pbmRleDogMTAwMDtcbiAgICAgICAgdG9wOiAxMHB4O1xuICAgICAgICByaWdodDogMTBweDtcbiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgIH1cblxuICAgICAgLmltZ19wcmV2aWV3IGltZyB7XG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIH1cbiAgICBgLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBOR1hJbWdab29tVmlld2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xuICBwcml2YXRlIGhvc3Q6IEhUTUxFbGVtZW50OyAvLyBBY2Nlc3MgZm9yIEhvc3QgRWxlbWVudFxuICBwcml2YXRlIGltYWdlITogSFRNTEltYWdlRWxlbWVudDsgLy8gSW1hZ2UgRWxlbWVudFxuICBwcml2YXRlIGN1cnNvciE6IEhUTUxEaXZFbGVtZW50OyAvLyBDdXJzb3IgRWxlbWVudFxuICBwcml2YXRlIGltZ19wcmV2aWV3ITogSFRNTERpdkVsZW1lbnQ7IC8vIEltYWdlIFByZXZpZXcgRWxlbWVudFxuXG4gIEBJbnB1dCgpIGNvbmZpZz86IGltZ1pvb21WaWV3ZXJDb25maWc7XG4gIEBJbnB1dCgpIHNldCBzcmMoc3JjVmFsdWU6IHN0cmluZykge1xuICAgIGlmICh0eXBlb2Ygc3JjVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aGlzLl9zcmMgPSBzcmNWYWx1ZTtcbiAgICAgIHRoaXMuY3JlYXRlSW1hZ2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgJ3NyYyBtdXN0IGJlIG9mIHR5cGUgc3RyaW5nLCBjdXJyZW50IHR5cGUgZm91bmQgJyArIHR5cGVvZiBzcmNWYWx1ZVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHByb3ZpZGVkUHJldmlld0JveDoge1xuICAgIGhlaWdodDogbnVtYmVyO1xuICAgIHdpZHRoOiBudW1iZXI7XG4gIH0gPSB7IGhlaWdodDogMzUwLCB3aWR0aDogMzUwIH07XG5cbiAgcHJpdmF0ZSBkZWZhdWx0Q29uZmlncyA9IHtcbiAgICBpbWdIZWlnaHQ6IDUwMCxcbiAgICBtZWduaWZpY2F0aW9uOiAyLjUsXG4gICAgcHJpdmlld0JveFNpemU6IHtcbiAgICAgIGhlaWdodDogMzUwLFxuICAgICAgd2lkdGg6IDM1MCxcbiAgICB9LFxuICB9O1xuXG4gIGRvY3VtZW50OiBEb2N1bWVudDtcblxuICBwcml2YXRlIGN1cnNvclNpemU6IHtcbiAgICBoZWlnaHQ6IG51bWJlcjtcbiAgICB3aWR0aDogbnVtYmVyO1xuICB9ID0geyBoZWlnaHQ6IDAsIHdpZHRoOiAwIH07XG5cbiAgcHJpdmF0ZSBfc3JjOiBzdHJpbmcgPSAnJztcblxuICBwcml2YXRlIGN1cnNvclBvc2l0aW9uOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0gPSB7IHg6IDAsIHk6IDAgfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsOiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMixcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBkb2N1bWVudDogRG9jdW1lbnRcbiAgKSB7XG4gICAgdGhpcy5ob3N0ID0gdGhpcy5yZW5kZXJlci5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICB0aGlzLmRvY3VtZW50ID0gZG9jdW1lbnQ7XG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLmhvc3QsICdpbWFnZV9jb250YWluZXInKTtcbiAgICB0aGlzLnJlbmRlcmVyLmFwcGVuZENoaWxkKGVsLm5hdGl2ZUVsZW1lbnQsIHRoaXMuaG9zdCk7IC8vIGFzc2lnbmluZyBob3N0XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgdGhpcy5kZWZhdWx0Q29uZmlncy5pbWdIZWlnaHQgPVxuICAgICAgdGhpcy5jb25maWc/LmltZ0hlaWdodCA/PyB0aGlzLmRlZmF1bHRDb25maWdzLmltZ0hlaWdodDtcblxuICAgIHRoaXMuZGVmYXVsdENvbmZpZ3MubWVnbmlmaWNhdGlvbiA9XG4gICAgICB0aGlzLmNvbmZpZz8ubWVnbmlmaWNhdGlvbiA/PyB0aGlzLmRlZmF1bHRDb25maWdzLm1lZ25pZmljYXRpb247XG5cbiAgICB0aGlzLmRlZmF1bHRDb25maWdzLnByaXZpZXdCb3hTaXplLmhlaWdodCA9XG4gICAgICB0aGlzLmNvbmZpZz8ucHJpdmlld0JveFNpemU/LmhlaWdodCA/P1xuICAgICAgdGhpcy5kZWZhdWx0Q29uZmlncy5wcml2aWV3Qm94U2l6ZS5oZWlnaHQ7XG5cbiAgICBpZiAodGhpcy5kZWZhdWx0Q29uZmlncy5wcml2aWV3Qm94U2l6ZS5oZWlnaHQgKyAyMCA+IHdpbmRvdy5pbm5lckhlaWdodCkge1xuICAgICAgdGhpcy5kZWZhdWx0Q29uZmlncy5wcml2aWV3Qm94U2l6ZS5oZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQgLSAyMDtcbiAgICB9XG5cbiAgICB0aGlzLmRlZmF1bHRDb25maWdzLnByaXZpZXdCb3hTaXplLndpZHRoID1cbiAgICAgIHRoaXMuZGVmYXVsdENvbmZpZ3MucHJpdmlld0JveFNpemUuaGVpZ2h0O1xuICAgIHRoaXMucHJvdmlkZWRQcmV2aWV3Qm94ID0geyAuLi50aGlzLmRlZmF1bHRDb25maWdzLnByaXZpZXdCb3hTaXplIH07XG4gICAgdGhpcy5jcmVhdGVJbWFnZSgpO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9zcmMpIGNvbnNvbGUuZXJyb3IoJ3VuYWJsZSB0byByZWFkIHNyYyBhdHRyaWJ1dGUnKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCBbJyRldmVudCddKVxuICBwcml2YXRlIG9uTW91c2VMZWF2ZShlOiBNb3VzZUV2ZW50KSB7XG4gICAgaWYgKHRoaXMuY3Vyc29yU2l6ZS53aWR0aCA8IDUwICYmIHRoaXMuY3Vyc29yU2l6ZS5oZWlnaHQgPiA1MCkgcmV0dXJuO1xuICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2hpbGQodGhpcy5ob3N0LCB0aGlzLmN1cnNvcik7XG4gICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDaGlsZCh0aGlzLmRvY3VtZW50LCB0aGlzLmltZ19wcmV2aWV3KTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlZW50ZXInLCBbJyRldmVudCddKVxuICBwcml2YXRlIG9uTW91c2VFbnRlcihlOiBNb3VzZUV2ZW50KSB7XG4gICAgdGhpcy5jaGVja3dpZHRoKCk7XG4gICAgaWYgKHRoaXMuY3Vyc29yU2l6ZS53aWR0aCA8IDUwICYmIHRoaXMuY3Vyc29yU2l6ZS5oZWlnaHQgPiA1MCkgcmV0dXJuO1xuICAgIGlmICh0aGlzLmhvc3QuY2hpbGRyZW4ubGVuZ3RoID4gMSkge1xuICAgICAgdGhpcy5vbk1vdXNlTGVhdmUoZSk7XG4gICAgfVxuICAgIGlmICh0aGlzLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCduZ3gtaW1nLXpvb20tdmlld2VyJykpIHtcbiAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2hpbGQoXG4gICAgICAgIHRoaXMuZG9jdW1lbnQsXG4gICAgICAgIHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ25neC1pbWctem9vbS12aWV3ZXInKVxuICAgICAgKTtcbiAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2hpbGQoXG4gICAgICAgIHRoaXMuZG9jdW1lbnQsXG4gICAgICAgIHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ25neC1pbWctem9vbS1jdXJzb3InKVxuICAgICAgKTtcbiAgICB9XG4gICAgdGhpcy5jdXJzb3IgPSB0aGlzLnJlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5jdXJzb3IsICdjdXJzb3InKTtcbiAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgdGhpcy5jdXJzb3IsXG4gICAgICBgaGVpZ2h0YCxcbiAgICAgIGAke3RoaXMuY3Vyc29yU2l6ZT8uaGVpZ2h0fXB4YFxuICAgICk7XG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmN1cnNvciwgYHdpZHRoYCwgYCR7dGhpcy5jdXJzb3JTaXplPy53aWR0aH1weGApO1xuICAgIHRoaXMucmVuZGVyZXIuc2V0QXR0cmlidXRlKHRoaXMuY3Vyc29yLCAnaWQnLCAnbmd4LWltZy16b29tLWN1cnNvcicpO1xuICAgIHRoaXMucmVuZGVyZXIuYXBwZW5kQ2hpbGQodGhpcy5ob3N0LCB0aGlzLmN1cnNvcik7XG4gICAgdGhpcy5zZXRDdXJzb3JQb3NpdGlvbihlKTtcblxuICAgIHRoaXMuaW1nX3ByZXZpZXcgPSB0aGlzLnJlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5pbWdfcHJldmlldywgJ2ltZ19wcmV2aWV3Jyk7XG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgIHRoaXMuaW1nX3ByZXZpZXcsXG4gICAgICAnaGVpZ2h0JyxcbiAgICAgIGAke3RoaXMuZGVmYXVsdENvbmZpZ3MucHJpdmlld0JveFNpemUuaGVpZ2h0fXB4YFxuICAgICk7XG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgIHRoaXMuaW1nX3ByZXZpZXcsXG4gICAgICAnd2lkdGgnLFxuICAgICAgYCR7dGhpcy5kZWZhdWx0Q29uZmlncy5wcml2aWV3Qm94U2l6ZS53aWR0aH1weGBcbiAgICApO1xuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICB0aGlzLmltZ19wcmV2aWV3LFxuICAgICAgJ2xlZnQnLFxuICAgICAgYCR7d2luZG93LmlubmVyV2lkdGggLSAxMCAtIHRoaXMuZGVmYXVsdENvbmZpZ3MucHJpdmlld0JveFNpemUud2lkdGh9cHhgXG4gICAgKTtcbiAgICB0aGlzLnJlbmRlcmVyLnNldEF0dHJpYnV0ZSh0aGlzLmltZ19wcmV2aWV3LCAnaWQnLCAnbmd4LWltZy16b29tLXZpZXdlcicpO1xuICAgIHRoaXMucmVuZGVyZXIuYXBwZW5kQ2hpbGQoXG4gICAgICB0aGlzLmhvc3Qub3duZXJEb2N1bWVudC5sYXN0Q2hpbGQ/Lmxhc3RDaGlsZCxcbiAgICAgIHRoaXMuaW1nX3ByZXZpZXdcbiAgICApO1xuICB9XG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlbW92ZScsIFsnJGV2ZW50J10pXG4gIHByaXZhdGUgb25Nb3VzZU1vdmUoZTogTW91c2VFdmVudCkge1xuICAgIGlmICh0aGlzLmN1cnNvclNpemUud2lkdGggPCA1MCAmJiB0aGlzLmN1cnNvclNpemUuaGVpZ2h0ID4gNTApIHJldHVybjtcbiAgICB0aGlzLnNldEN1cnNvclBvc2l0aW9uKGUpO1xuICAgIHRoaXMuc2V0SW1nUHJldmlldyhlKTtcbiAgfVxuICBwcml2YXRlIHNldEN1cnNvclBvc2l0aW9uKGU6IE1vdXNlRXZlbnQpIHtcbiAgICAvKiBoYW5kbGluZyBMZWZ0ICYgdG9wIHBvc2l0aW9uIGZvciBjdXJzb3IgYm94ICovXG4gICAgY29uc3QgaW1hZ2V4ID0gdGhpcy5pbWFnZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS54O1xuICAgIGNvbnN0IGltYWdleSA9IHRoaXMuaW1hZ2UuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkueTtcbiAgICBsZXQgY3Vyc29yUG9zaXRpb24gPSB7XG4gICAgICB4OlxuICAgICAgICBlLnBhZ2VYIC0gdGhpcy5jdXJzb3JTaXplPy53aWR0aCAvIDIgLSBpbWFnZXggPj0gMCAvLyBjaGVja2luZyBpZiBjdXJzb3IgYm94IGxlZnQgaXMgbGVzcyB0aGVuIDBcbiAgICAgICAgICA/IGUucGFnZVggLSB0aGlzLmN1cnNvclNpemU/LndpZHRoIC8gMiAtIGltYWdleFxuICAgICAgICAgIDogMCwgLy8gbWFraW5nIHN1cmUgaWYgaXQgaXMgdGhlbiBvbmx5IHRha2UgMCBub3QgbmVnYXRpdmUgdmFsdWVcbiAgICAgIHk6XG4gICAgICAgIGUucGFnZVkgLSB0aGlzLmN1cnNvclNpemU/LmhlaWdodCAvIDIgLSBpbWFnZXkgPj0gMCAvLyBjaGVja2luZyBpZiBjdXJzb3IgYm94IHRvcCBpcyBsZXNzIHRoZW4gMFxuICAgICAgICAgID8gZS5wYWdlWSAtIHRoaXMuY3Vyc29yU2l6ZT8uaGVpZ2h0IC8gMiAtIGltYWdleVxuICAgICAgICAgIDogMCwgLy8gbWFraW5nIHN1cmUgaWYgaXQgaXMgdGhlbiBvbmx5IHRha2UgMCBub3QgbmVnYXRpdmUgdmFsdWVcbiAgICB9O1xuXG4gICAgLyogaGFuZGxpbmcgYm90dG9tICYgcmlnaHQgcG9zaXRpb24gZm9yIGN1cnNvciBib3ggKi9cbiAgICBpZiAoY3Vyc29yUG9zaXRpb24ueCArIHRoaXMuY3Vyc29yU2l6ZT8ud2lkdGggPiB0aGlzLmltYWdlLm9mZnNldFdpZHRoKSB7XG4gICAgICAvLyBjaGVja2luZyBpZiBjdXJzb3IgbGVmdCArIGN1cnNvciB3aWR0aCBpcyBncmVhdGVyIHRoZW4gaW1hZ2Ugd2lkdGhcbiAgICAgIC8vIG1ha2luZyBzdXJlIHRoYXQgYW55IHNpbmdsZSBwaXhlbCBvZiBjdXJzb3IgYm94IGNhbid0IGdvIG91dCBmcm9tIGltYWdlIHJlc3BlY3RpdmUgb24gd2lkdGhcbiAgICAgIGN1cnNvclBvc2l0aW9uLnggPSB0aGlzLmltYWdlLm9mZnNldFdpZHRoIC0gdGhpcy5jdXJzb3JTaXplPy53aWR0aDtcbiAgICB9XG4gICAgaWYgKGN1cnNvclBvc2l0aW9uLnkgKyB0aGlzLmN1cnNvclNpemU/LmhlaWdodCA+IHRoaXMuaW1hZ2Uub2Zmc2V0SGVpZ2h0KSB7XG4gICAgICAvLyBtYWtpbmcgc3VyZSB0aGF0IGFueSBzaW5nbGUgcGl4ZWwgb2YgY3Vyc29yIGJveCBjYW4ndCBnbyBvdXQgZnJvbSBpbWFnZSByZXNwZWN0aXZlIG9uIGhlaWdodFxuICAgICAgY3Vyc29yUG9zaXRpb24ueSA9IHRoaXMuaW1hZ2Uub2Zmc2V0SGVpZ2h0IC0gdGhpcy5jdXJzb3JTaXplPy5oZWlnaHQ7XG4gICAgfVxuXG4gICAgLyogc2V0dGluZyBmaW5hbCB2YWx1ZSAqL1xuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5jdXJzb3IsICd0b3AnLCBgJHtjdXJzb3JQb3NpdGlvbi55fXB4YCk7IC8vIHNldHRpbmcgY3Vyc29yIGJveCBwb3NpdGlvbiBmb3IgeSBheGlzXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmN1cnNvciwgJ2xlZnQnLCBgJHtjdXJzb3JQb3NpdGlvbi54fXB4YCk7IC8vIHNldHRpbmcgY3Vyc29yIGJveCBwb3NpdGlvbiBmb3IgeCBheGlzXG5cbiAgICB0aGlzLmN1cnNvclBvc2l0aW9uID0gY3Vyc29yUG9zaXRpb247IC8vIHNhdmluZyBkYXRhIHRvIGdsb2JhbCB2YXJpYWJsZVxuICB9XG4gIHByaXZhdGUgc2V0SW1nUHJldmlldyhlOiBNb3VzZUV2ZW50KSB7XG4gICAgY29uc3Qgem9vbWVkSW1hZ2UgPSB0aGlzLnJlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoJ2ltZycpOyAvLyBjcmVhdGVkIG5ldyBsb2NhbCBpbWFnZSBlbGVtZW50XG4gICAgdGhpcy5yZW5kZXJlci5zZXRBdHRyaWJ1dGUoem9vbWVkSW1hZ2UsICdzcmMnLCB0aGlzLl9zcmMpOyAvLyBzZXR0aW5nIHNyYyBmb3IgbG9jYWwgaW1hZ2UgZWxlbWVudFxuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICB6b29tZWRJbWFnZSxcbiAgICAgICdoZWlnaHQnLFxuICAgICAgYCR7dGhpcy5pbWFnZS5vZmZzZXRIZWlnaHQgKiB0aGlzLmRlZmF1bHRDb25maWdzLm1lZ25pZmljYXRpb259cHhgXG4gICAgKTsgLy8gY2hhbmdlZCB6b29tZWQgaW1hZ2UgaGVpZ2h0IGJhc2VkIG9uIHJlYWwgaW1hZ2VcbiAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgem9vbWVkSW1hZ2UsXG4gICAgICAnd2lkdGgnLFxuICAgICAgYCR7dGhpcy5pbWFnZS5vZmZzZXRXaWR0aCAqIHRoaXMuZGVmYXVsdENvbmZpZ3MubWVnbmlmaWNhdGlvbn1weGBcbiAgICApOyAvLyBjaGFuZ2VkIHpvb21lZCBpbWFnZSB3aWR0aCBiYXNlZCBvbiByZWFsIGltYWdlXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgIHpvb21lZEltYWdlLFxuICAgICAgJ3RvcCcsXG4gICAgICBgLSR7dGhpcy5jdXJzb3JQb3NpdGlvbi55ICogdGhpcy5kZWZhdWx0Q29uZmlncy5tZWduaWZpY2F0aW9ufXB4YFxuICAgICk7IC8vIGNoYW5nZWQgem9vbWVkIGltYWdlIHBvc2l0aW9uIGJhc2VkIG9uIGN1cnNvciBwb3NpdGlvblxuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICB6b29tZWRJbWFnZSxcbiAgICAgICdsZWZ0JyxcbiAgICAgIGAtJHt0aGlzLmN1cnNvclBvc2l0aW9uLnggKiB0aGlzLmRlZmF1bHRDb25maWdzLm1lZ25pZmljYXRpb259cHhgXG4gICAgKTsgLy8gY2hhbmdlZCB6b29tZWQgaW1hZ2UgcG9zaXRpb24gYmFzZWQgb24gY3Vyc29yIHBvc2l0aW9uXG4gICAgdGhpcy5pbWdfcHJldmlldy5pbm5lckhUTUwgPSAnJztcbiAgICB0aGlzLnJlbmRlcmVyLmFwcGVuZENoaWxkKHRoaXMuaW1nX3ByZXZpZXcsIHpvb21lZEltYWdlKTsgLy8gYWRkZWQgaW1hZ2UgaW50byBpbWdfcHJldmlldyBib3hcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlSW1hZ2UoKSB7XG4gICAgdGhpcy5ob3N0LmlubmVySFRNTCA9ICcnO1xuICAgIHRoaXMuaW1hZ2UgPSB0aGlzLnJlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIHRoaXMucmVuZGVyZXIuc2V0QXR0cmlidXRlKHRoaXMuaW1hZ2UsICdzcmMnLCB0aGlzLl9zcmMpO1xuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5pbWFnZSwgJ21haW5faW1hZ2UnKTtcbiAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgdGhpcy5pbWFnZSxcbiAgICAgICdtYXgtaGVpZ2h0JyxcbiAgICAgIHRoaXMuZGVmYXVsdENvbmZpZ3MuaW1nSGVpZ2h0ICsgJ3B4J1xuICAgICk7XG4gICAgdGhpcy5yZW5kZXJlci5hcHBlbmRDaGlsZCh0aGlzLmhvc3QsIHRoaXMuaW1hZ2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja3dpZHRoKCkge1xuICAgIHRoaXMuZGVmYXVsdENvbmZpZ3MucHJpdmlld0JveFNpemUud2lkdGggPSB0aGlzLnByb3ZpZGVkUHJldmlld0JveC53aWR0aDtcbiAgICBjb25zdCBkZWYgPVxuICAgICAgdGhpcy5pbWFnZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS54ICtcbiAgICAgIHRoaXMuaW1hZ2Uud2lkdGggK1xuICAgICAgdGhpcy5kZWZhdWx0Q29uZmlncy5wcml2aWV3Qm94U2l6ZS53aWR0aCArXG4gICAgICAyMCAtXG4gICAgICB3aW5kb3cuaW5uZXJXaWR0aDtcblxuICAgIGlmIChkZWYgPj0gMCkge1xuICAgICAgdGhpcy5kZWZhdWx0Q29uZmlncy5wcml2aWV3Qm94U2l6ZS53aWR0aCA9XG4gICAgICAgIHRoaXMuZGVmYXVsdENvbmZpZ3MucHJpdmlld0JveFNpemUud2lkdGggLSBkZWYgLSAzMDtcbiAgICB9XG5cbiAgICB0aGlzLmN1cnNvclNpemUuaGVpZ2h0ID1cbiAgICAgIHRoaXMuZGVmYXVsdENvbmZpZ3MucHJpdmlld0JveFNpemUuaGVpZ2h0IC9cbiAgICAgIHRoaXMuZGVmYXVsdENvbmZpZ3MubWVnbmlmaWNhdGlvbjtcblxuICAgIHRoaXMuY3Vyc29yU2l6ZS53aWR0aCA9XG4gICAgICB0aGlzLmRlZmF1bHRDb25maWdzLnByaXZpZXdCb3hTaXplLndpZHRoIC9cbiAgICAgIHRoaXMuZGVmYXVsdENvbmZpZ3MubWVnbmlmaWNhdGlvbjtcbiAgfVxufVxuIl19