UNPKG

ng-canvas-paint

Version:

Esta libreria fue generada con [Angular CLI](https://github.com/angular/angular-cli) version 8.2.9.

270 lines 33.4 kB
import { Component, Input, Output, EventEmitter } from '@angular/core'; export class NgCanvasPaintComponent { constructor() { this.value = undefined; this.onValue = new EventEmitter(); this.containerClass = ''; this.headerClass = 'options-container'; this.painterContainerClass = 'ng-canvas-container'; this.confirmBtnClass = 'confirm-button'; this.cleanBtnClass = 'clean-button'; this.title = "Firmar en el recuadro"; this.color = "black"; this.backgroundColor = "white"; this.iconAcceptButton = "icon-check"; //"fas fa-check"; this.iconCleanButton = "icon-clean"; //"fas fa-redo-alt"; this.onAccept = new EventEmitter(); this.onRefresh = new EventEmitter(); this.positionButtons = "bottom" || "top"; } ngOnInit() { } ngAfterViewInit() { setColor(this.color, this.backgroundColor); let time = setTimeout((_) => init(), 100); } refreshCanvas() { if (this.value) this.value = undefined; setTimeout(() => { canvasClear(); init(); this.onRefresh.emit(); }, 500); } guardarCanvas() { this.value = canvasToImg(); this.onAccept.emit(this.value); } } NgCanvasPaintComponent.decorators = [ { type: Component, args: [{ selector: 'ng-canvas-paint', template: ` <div id="container" class="main-container" [ngClass]="containerClass" > <div [ngClass]="headerClass"> <p><strong>{{title}}</strong></p> <div class="buttons-container" *ngIf="positionButtons === 'top'"> <button type="button" [ngClass]="cleanBtnClass" (click)="refreshCanvas()"><i [ngClass]="iconCleanButton"></i></button> <button type="button" [ngClass]="confirmBtnClass" (click)="guardarCanvas()"><i [ngClass]="iconAcceptButton"></i></button> </div> </div> <div id="container-painter" [ngClass]="painterContainerClass"> <canvas id="canvasPainterView" class="canvas-painter" *ngIf="!value"> <p>Unfortunately, your browser is currently unsupported by our web application. We are sorry for the inconvenience. Please use one of the supported browsers listed below, or draw the image you want using an offline tool.</p> <p>Supported browsers: <a href="http://www.opera.com/">Opera</a>, <a href="http://www.mozilla.com/">Firefox</a>, <a href="http://www.apple.com/safari">Safari</a>, and <a href="http://www.konqueror.org/">Konqueror</a>.</p> </canvas> <img class="image-painter" [src]="value" *ngIf="value" /> </div> <div class="buttons-container" *ngIf="positionButtons === 'bottom'"> <button type="button" [ngClass]="cleanBtnClass" (click)="refreshCanvas()" title="Limpiar recuadro"><i [ngClass]="iconCleanButton"></i></button> <button type="button" [ngClass]="confirmBtnClass" (click)="guardarCanvas()" title="Confirmar firma"><i [ngClass]="iconAcceptButton"></i></button> </div> </div> `, styles: ["@charset \"UTF-8\";.main-container{display:flex;flex-direction:column}.ng-canvas-container{background:#ebf0f2;min-height:240px;width:100%;border:2px dashed #c2d1d9;border-radius:8px;display:flex;justify-content:center;align-items:center;flex-direction:column;margin-bottom:0;width:inherit;height:inherit;padding:0!important}.canvas-painter,.image-painter{width:inherit;height:inherit;display:block}.options-container{justify-content:space-between}.buttons-container,.options-container{width:inherit;display:flex;align-items:center}.buttons-container{justify-content:flex-end}.card-body{padding:0!important}.center{display:flex;flex-direction:row;align-items:center;justify-content:center}.confirm-button{color:#00695e}.clean-button,.confirm-button{background-color:initial;border:none;font-size:24px}.clean-button{color:#012c5b}.icon-clean:before{content:\"\u274C\"}.icon-check:before{content:\"\u2714\uFE0F\"}"] },] } ]; /** @nocollapse */ NgCanvasPaintComponent.ctorParameters = () => []; NgCanvasPaintComponent.propDecorators = { value: [{ type: Input, args: ['value',] }], onValue: [{ type: Output, args: ['value',] }], containerClass: [{ type: Input, args: ['containerClass',] }], headerClass: [{ type: Input, args: ['headerClass',] }], painterContainerClass: [{ type: Input, args: ['painterContainerClass',] }], confirmBtnClass: [{ type: Input, args: ['confirmBtnClass',] }], cleanBtnClass: [{ type: Input, args: ['cleanBtnClass',] }], title: [{ type: Input, args: ['title',] }], color: [{ type: Input, args: ['color',] }], backgroundColor: [{ type: Input, args: ['backgroundColor',] }], iconAcceptButton: [{ type: Input, args: ['iconAcceptButton',] }], iconCleanButton: [{ type: Input, args: ['iconCleanButton',] }], onAccept: [{ type: Output, args: ['onAccept',] }], onRefresh: [{ type: Output, args: ['onRefresh',] }], positionButtons: [{ type: Input, args: ['positionButtons',] }] }; var containerCanvas, canvas, context, tool, color, background, autoSave; function setColor(lineColor, backgroundColor) { color = lineColor; background = backgroundColor; } function init(saveAuto = true) { autoSave = saveAuto; // Find the canvas element. canvas = document.getElementById('canvasPainterView'); containerCanvas = document.getElementById("container-painter"); canvas.width = containerCanvas.offsetWidth; canvas.height = containerCanvas.offsetHeight; if (!canvas) { alert('Error: I cannot find the canvas element!'); return; } if (!canvas.getContext) { alert('Error: no canvas.getContext!'); return; } // Get the 2D canvas context. context = canvas.getContext('2d'); if (!context) { alert('Error: failed to getContext!'); return; } context.fillStyle = background; context.strokeStyle = color; context.fillRect(0, 0, canvas.width, canvas.height); var touchAvailable = ('createTouch' in document) || ('ontouchstart' in window); // Pencil tool instance. tool = new tool_pencil(); // Attach the mousedown, mousemove and mouseup event listeners. canvas.addEventListener('mousedown', ev_canvas, false); canvas.addEventListener('mousemove', ev_canvas, false); canvas.addEventListener('mouseup', ev_canvas, false); if (touchAvailable) { document.body.addEventListener('touchmove', function (event) { event.preventDefault(); }, { passive: false }); canvas.addEventListener('touchstart', ev_canvas, false); canvas.addEventListener('touchmove', function (e) { // stop touch event e.stopPropagation(); e.preventDefault(); // translate to mouse event var clkEvt = document.createEvent('MouseEvent'); clkEvt.initMouseEvent('mousemove', true, true, window, e.detail, e.touches[0].screenX, e.touches[0].screenY, e.touches[0].clientX, e.touches[0].clientY, false, false, false, false, 0, null); canvas.dispatchEvent(clkEvt); // or just handle touch event ev_canvas(e); }, false); //canvas.addEventListener('touchmove', draw, false); canvas.addEventListener('touchend', ev_canvas, false); } } // This painting tool works like a drawing pencil which tracks the mouse // movements. function tool_pencil() { tool = this; this.started = false; // This is called when you start holding down the mouse button. // This starts the pencil drawing. this.mousedown = function (ev) { context.beginPath(); context.moveTo(ev._x, ev._y); tool.started = true; }; // This function is called every time you move the mouse. Obviously, it only // draws if the tool.started state is set to true (when you are holding down // the mouse button). this.mousemove = function (ev) { if (tool.started) { context.lineTo(ev._x, ev._y); context.stroke(); } }; // This is called when you release the mouse button. this.mouseup = function (ev) { if (tool.started) { tool.mousemove(ev); tool.started = false; if (autoSave) { canvasToImg(); } } }; } // The general-purpose event handler. This function just determines the mouse // position relative to the canvas element. function ev_canvas(ev) { if (ev.layerX || ev.layerX == 0) { // Firefox ev._x = ev.layerX; ev._y = ev.layerY; } else if (ev.offsetX || ev.offsetX == 0) { // Opera ev._x = ev.offsetX; ev._y = ev.offsetY; } else if (ev.pageX || ev.pageX == 0) { ev._x = ev.pageX; ev._y = ev.pageY; } // Call the event handler of the tool. var type = null; switch (ev.type) { case "touchstart": type = "mousedown"; break; case "touchmove": type = "mousemove"; break; case "touchend": type = "mouseup"; break; default: type = ev.type; break; } ; var func = tool[type]; if (func) { func(ev); } } function canvasClear() { const context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); } function canvasToImg() { //var canvas = document.getElementById("canvasPainterView"); var ctx = canvas.getContext("2d"); //draw a red box ctx.fillStyle = background; ctx.strokeStyle = color; ctx.fillRect(10, 10, 30, 30); return canvas.toDataURL(); } const ɵ0 = function (coors) { context.beginPath(); context.moveTo(coors.x, coors.y); this.isDrawing = true; }, ɵ1 = function (coors) { if (this.isDrawing) { context.lineTo(coors.x, coors.y); context.stroke(); } }, ɵ2 = function (coors) { if (this.isDrawing) { this.touchmove(coors); this.isDrawing = false; } }; var drawer = { isDrawing: false, touchstart: ɵ0, touchmove: ɵ1, touchend: ɵ2 }; function draw(event) { var type = null; var coors; if (event.type === "touchend") { coors = { x: event.changedTouches[0].pageX, y: event.changedTouches[0].pageY }; } else { // get the touch coordinates coors = { x: event.touches[0].pageX, y: event.touches[0].pageY }; } type = type || event.type; // pass the coordinates to the appropriate handler drawer[type](coors); } export { ɵ0, ɵ1, ɵ2 }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctY2FudmFzLXBhaW50LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWNhbnZhcy1wYWludC9zcmMvbGliL25nLWNhbnZhcy1wYWludC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBeUIsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUErQjlGLE1BQU0sT0FBTyxzQkFBc0I7SUFvQmpDO1FBbEJnQixVQUFLLEdBQVEsU0FBUyxDQUFDO1FBQ3RCLFlBQU8sR0FBcUIsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUM1QyxtQkFBYyxHQUFHLEVBQUUsQ0FBQztRQUN2QixnQkFBVyxHQUFHLG1CQUFtQixDQUFDO1FBQ3hCLDBCQUFxQixHQUFHLHFCQUFxQixDQUFDO1FBQ3BELG9CQUFlLEdBQUcsZ0JBQWdCLENBQUM7UUFDckMsa0JBQWEsR0FBRyxjQUFjLENBQUM7UUFDdkMsVUFBSyxHQUFXLHVCQUF1QixDQUFDO1FBQ3hDLFVBQUssR0FBRyxPQUFPLENBQUM7UUFDTixvQkFBZSxHQUFHLE9BQU8sQ0FBQztRQUN6QixxQkFBZ0IsR0FBRyxZQUFZLENBQUMsQ0FBQSxpQkFBaUI7UUFDbEQsb0JBQWUsR0FBRyxZQUFZLENBQUMsQ0FBQSxvQkFBb0I7UUFFekQsYUFBUSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFDckMsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFL0Isb0JBQWUsR0FBVyxRQUFRLElBQUksS0FBSyxDQUFDO0lBR3ZFLENBQUM7SUFFRCxRQUFRO0lBRVIsQ0FBQztJQUVELGVBQWU7UUFDYixRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDM0MsSUFBSSxJQUFJLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFF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O0FBQ3RCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ25nLWNhbnZhcy1wYWludCcsXHJcbiAgdGVtcGxhdGU6IGBcclxuICAgIDxkaXYgaWQ9XCJjb250YWluZXJcIiBjbGFzcz1cIm1haW4tY29udGFpbmVyXCIgW25nQ2xhc3NdPVwiY29udGFpbmVyQ2xhc3NcIiA+XHJcbiAgICAgIDxkaXYgW25nQ2xhc3NdPVwiaGVhZGVyQ2xhc3NcIj5cclxuICAgICAgICA8cD48c3Ryb25nPnt7dGl0bGV9fTwvc3Ryb25nPjwvcD5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiYnV0dG9ucy1jb250YWluZXJcIiAqbmdJZj1cInBvc2l0aW9uQnV0dG9ucyA9PT0gJ3RvcCdcIj5cclxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIFtuZ0NsYXNzXT1cImNsZWFuQnRuQ2xhc3NcIiAoY2xpY2spPVwicmVmcmVzaENhbnZhcygpXCI+PGkgW25nQ2xhc3NdPVwiaWNvbkNsZWFuQnV0dG9uXCI+PC9pPjwvYnV0dG9uPlxyXG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW25nQ2xhc3NdPVwiY29uZmlybUJ0bkNsYXNzXCIgKGNsaWNrKT1cImd1YXJkYXJDYW52YXMoKVwiPjxpIFtuZ0NsYXNzXT1cImljb25BY2NlcHRCdXR0b25cIj48L2k+PC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cdFx0XHQ8ZGl2IGlkPVwiY29udGFpbmVyLXBhaW50ZXJcIiBbbmdDbGFzc109XCJwYWludGVyQ29udGFpbmVyQ2xhc3NcIj5cclxuICAgICAgICA8Y2FudmFzIGlkPVwiY2FudmFzUGFpbnRlclZpZXdcIiBjbGFzcz1cImNhbnZhcy1wYWludGVyXCIgKm5nSWY9XCIhdmFsdWVcIj5cclxuXHRcdFx0XHQ8cD5VbmZvcnR1bmF0ZWx5LCB5b3VyIGJyb3dzZXIgaXMgY3VycmVudGx5IHVuc3VwcG9ydGVkIGJ5IG91ciB3ZWIgYXBwbGljYXRpb24uIFdlIGFyZSBzb3JyeSBmb3IgdGhlXHJcblx0XHRcdFx0ICBpbmNvbnZlbmllbmNlLiBQbGVhc2UgdXNlIG9uZSBvZiB0aGUgc3VwcG9ydGVkIGJyb3dzZXJzIGxpc3RlZCBiZWxvdywgb3IgZHJhdyB0aGUgaW1hZ2UgeW91IHdhbnQgdXNpbmcgYW5cclxuXHRcdFx0XHQgIG9mZmxpbmUgdG9vbC48L3A+XHJcblx0XHRcdFx0PHA+U3VwcG9ydGVkIGJyb3dzZXJzOiA8YSBocmVmPVwiaHR0cDovL3d3dy5vcGVyYS5jb20vXCI+T3BlcmE8L2E+LCA8YSBocmVmPVwiaHR0cDovL3d3dy5tb3ppbGxhLmNvbS9cIj5GaXJlZm94PC9hPixcclxuXHRcdFx0XHQgIDxhIGhyZWY9XCJodHRwOi8vd3d3LmFwcGxlLmNvbS9zYWZhcmlcIj5TYWZhcmk8L2E+LCBhbmQgPGEgaHJlZj1cImh0dHA6Ly93d3cua29ucXVlcm9yLm9yZy9cIj5Lb25xdWVyb3I8L2E+LjwvcD5cclxuXHRcdFx0ICA8L2NhbnZhcz5cclxuXHRcdFx0ICA8aW1nIGNsYXNzPVwiaW1hZ2UtcGFpbnRlclwiIFtzcmNdPVwidmFsdWVcIiAqbmdJZj1cInZhbHVlXCIgLz5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJidXR0b25zLWNvbnRhaW5lclwiICpuZ0lmPVwicG9zaXRpb25CdXR0b25zID09PSAnYm90dG9tJ1wiPlxyXG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIFtuZ0NsYXNzXT1cImNsZWFuQnRuQ2xhc3NcIiAoY2xpY2spPVwicmVmcmVzaENhbnZhcygpXCIgdGl0bGU9XCJMaW1waWFyIHJlY3VhZHJvXCI+PGkgW25nQ2xhc3NdPVwiaWNvbkNsZWFuQnV0dG9uXCI+PC9pPjwvYnV0dG9uPlxyXG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIFtuZ0NsYXNzXT1cImNvbmZpcm1CdG5DbGFzc1wiIChjbGljayk9XCJndWFyZGFyQ2FudmFzKClcIiB0aXRsZT1cIkNvbmZpcm1hciBmaXJtYVwiPjxpIFtuZ0NsYXNzXT1cImljb25BY2NlcHRCdXR0b25cIj48L2k+PC9idXR0b24+XHJcbiAgICAgIDwvZGl2PlxyXG5cdDwvZGl2PlxyXG4gIGAsXHJcbiAgc3R5bGVVcmxzOiBbJ25nLWNhbnZhcy1wYWludC5jb21wb25lbnQuc2NzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBOZ0NhbnZhc1BhaW50Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcclxuXHJcbiAgQElucHV0KCd2YWx1ZScpIHZhbHVlOiBhbnkgPSB1bmRlZmluZWQ7XHJcbiAgQE91dHB1dCgndmFsdWUnKSBvblZhbHVlOkV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQElucHV0KCdjb250YWluZXJDbGFzcycpIGNvbnRhaW5lckNsYXNzID0gJyc7XHJcbiAgQElucHV0KCdoZWFkZXJDbGFzcycpIGhlYWRlckNsYXNzID0gJ29wdGlvbnMtY29udGFpbmVyJztcclxuICBASW5wdXQoJ3BhaW50ZXJDb250YWluZXJDbGFzcycpIHBhaW50ZXJDb250YWluZXJDbGFzcyA9ICduZy1jYW52YXMtY29udGFpbmVyJztcclxuICBASW5wdXQoJ2NvbmZpcm1CdG5DbGFzcycpIGNvbmZpcm1CdG5DbGFzcyA9ICdjb25maXJtLWJ1dHRvbic7XHJcbiAgQElucHV0KCdjbGVhbkJ0bkNsYXNzJykgY2xlYW5CdG5DbGFzcyA9ICdjbGVhbi1idXR0b24nO1xyXG4gIEBJbnB1dCgndGl0bGUnKSB0aXRsZTogc3RyaW5nID0gXCJGaXJtYXIgZW4gZWwgcmVjdWFkcm9cIjtcclxuICBASW5wdXQoJ2NvbG9yJykgY29sb3IgPSBcImJsYWNrXCI7XHJcbiAgQElucHV0KCdiYWNrZ3JvdW5kQ29sb3InKSBiYWNrZ3JvdW5kQ29sb3IgPSBcIndoaXRlXCI7XHJcbiAgQElucHV0KCdpY29uQWNjZXB0QnV0dG9uJykgaWNvbkFjY2VwdEJ1dHRvbiA9IFwiaWNvbi1jaGVja1wiOy8vXCJmYXMgZmEtY2hlY2tcIjtcclxuICBASW5wdXQoJ2ljb25DbGVhbkJ1dHRvbicpIGljb25DbGVhbkJ1dHRvbiA9IFwiaWNvbi1jbGVhblwiOy8vXCJmYXMgZmEtcmVkby1hbHRcIjtcclxuXHJcbiAgQE91dHB1dCgnb25BY2NlcHQnKSBvbkFjY2VwdCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG4gIEBPdXRwdXQoJ29uUmVmcmVzaCcpIG9uUmVmcmVzaCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuXHJcbiAgQElucHV0KCdwb3NpdGlvbkJ1dHRvbnMnKSAgcG9zaXRpb25CdXR0b25zOiBzdHJpbmcgPSBcImJvdHRvbVwiIHx8IFwidG9wXCI7XHJcblxyXG4gIGNvbnN0cnVjdG9yKCkge1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcblxyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgc2V0Q29sb3IodGhpcy5jb2xvciwgdGhpcy5iYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgbGV0IHRpbWUgPSBzZXRUaW1lb3V0KChfKSA9PiBpbml0KCksIDEwMCk7XHJcbiAgfVxyXG5cclxuICByZWZyZXNoQ2FudmFzKCkge1xyXG4gICAgaWYgKHRoaXMudmFsdWUpXHJcbiAgICAgIHRoaXMudmFsdWUgPSB1bmRlZmluZWQ7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgY2FudmFzQ2xlYXIoKTtcclxuICAgICAgaW5pdCgpO1xyXG4gICAgICB0aGlzLm9uUmVmcmVzaC5lbWl0KCk7XHJcbiAgICB9LCA1MDApO1xyXG4gIH1cclxuXHJcbiAgZ3VhcmRhckNhbnZhcygpIHtcclxuICAgIHRoaXMudmFsdWUgPSBjYW52YXNUb0ltZygpO1xyXG4gICAgdGhpcy5vbkFjY2VwdC5lbWl0KHRoaXMudmFsdWUpO1xyXG4gIH1cclxuXHJcbn1cclxuXHJcbnZhciBjb250YWluZXJDYW52YXMsIGNhbnZhcywgY29udGV4dCwgdG9vbCwgY29sb3IsIGJhY2tncm91bmQsIGF1dG9TYXZlO1xyXG5cclxuZnVuY3Rpb24gc2V0Q29sb3IobGluZUNvbG9yLCBiYWNrZ3JvdW5kQ29sb3IpIHtcclxuICBjb2xvciA9IGxpbmVDb2xvcjtcclxuICBiYWNrZ3JvdW5kID0gYmFja2dyb3VuZENvbG9yO1xyXG59XHJcblxyXG5mdW5jdGlvbiBpbml0KHNhdmVBdXRvID0gdHJ1ZSkge1xyXG4gIGF1dG9TYXZlID0gc2F2ZUF1dG87XHJcblxyXG4gIC8vIEZpbmQgdGhlIGNhbnZhcyBlbGVtZW50LlxyXG4gIGNhbnZhcyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjYW52YXNQYWludGVyVmlldycpO1xyXG4gIGNvbnRhaW5lckNhbnZhcyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiY29udGFpbmVyLXBhaW50ZXJcIik7XHJcbiAgY2FudmFzLndpZHRoID0gY29udGFpbmVyQ2FudmFzLm9mZnNldFdpZHRoO1xyXG4gIGNhbnZhcy5oZWlnaHQgPSBjb250YWluZXJDYW52YXMub2Zmc2V0SGVpZ2h0O1xyXG4gIGlmICghY2FudmFzKSB7XHJcbiAgICBhbGVydCgnRXJyb3I6IEkgY2Fubm90IGZpbmQgdGhlIGNhbnZhcyBlbGVtZW50IScpO1xyXG4gICAgcmV0dXJuO1xyXG4gIH1cclxuXHJcbiAgaWYgKCFjYW52YXMuZ2V0Q29udGV4dCkge1xyXG4gICAgYWxlcnQoJ0Vycm9yOiBubyBjYW52YXMuZ2V0Q29udGV4dCEnKTtcclxuICAgIHJldHVybjtcclxuICB9XHJcblxyXG4gIC8vIEdldCB0aGUgMkQgY2FudmFzIGNvbnRleHQuXHJcbiAgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xyXG4gIGlmICghY29udGV4dCkge1xyXG4gICAgYWxlcnQoJ0Vycm9yOiBmYWlsZWQgdG8gZ2V0Q29udGV4dCEnKTtcclxuICAgIHJldHVybjtcclxuICB9XHJcblxyXG4gIGNvbnRleHQuZmlsbFN0eWxlID0gYmFja2dyb3VuZDtcclxuICBjb250ZXh0LnN0cm9rZVN0eWxlID0gY29sb3I7XHJcbiAgY29udGV4dC5maWxsUmVjdCgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xyXG5cclxuICB2YXIgdG91Y2hBdmFpbGFibGUgPSAoJ2NyZWF0ZVRvdWNoJyBpbiBkb2N1bWVudCkgfHwgKCdvbnRvdWNoc3RhcnQnIGluIHdpbmRvdyk7XHJcbiAgIFxyXG4gIC8vIFBlbmNpbCB0b29sIGluc3RhbmNlLlxyXG4gICB0b29sID0gbmV3IHRvb2xfcGVuY2lsKCk7XHJcbiAgIC8vIEF0dGFjaCB0aGUgbW91c2Vkb3duLCBtb3VzZW1vdmUgYW5kIG1vdXNldXAgZXZlbnQgbGlzdGVuZXJzLiBcclxuICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGV2X2NhbnZhcywgZmFsc2UpO1xyXG4gICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgZXZfY2FudmFzLCBmYWxzZSk7XHJcbiAgIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgZXZfY2FudmFzLCBmYWxzZSk7XHJcblxyXG4gIGlmICh0b3VjaEF2YWlsYWJsZSkge1xyXG4gICAgZG9jdW1lbnQuYm9keS5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcclxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIH0sIHsgcGFzc2l2ZTogZmFsc2UgfSk7XHJcbiAgICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIGV2X2NhbnZhcywgZmFsc2UpO1xyXG4gICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIC8vIHN0b3AgdG91Y2ggZXZlbnRcclxuICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gIFxyXG4gICAgICAvLyB0cmFuc2xhdGUgdG8gbW91c2UgZXZlbnRcclxuICAgICAgdmFyIGNsa0V2dCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50Jyk7XHJcbiAgICAgIGNsa0V2dC5pbml0TW91c2VFdmVudCgnbW91c2Vtb3ZlJywgdHJ1ZSwgdHJ1ZSwgd2luZG93LCBlLmRldGFpbCwgXHJcbiAgICAgICAgICAgICAgICAgICBlLnRvdWNoZXNbMF0uc2NyZWVuWCwgZS50b3VjaGVzWzBdLnNjcmVlblksIFxyXG4gICAgICAgICAgICAgICAgICAgZS50b3VjaGVzWzBdLmNsaWVudFgsIGUudG91Y2hlc1swXS5jbGllbnRZLCBcclxuICAgICAgICAgICAgICAgICAgIGZhbHNlLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBcclxuICAgICAgICAgICAgICAgICAgIDAsIG51bGwpO1xyXG4gICAgICBjYW52YXMuZGlzcGF0Y2hFdmVudChjbGtFdnQpO1xyXG4gIFxyXG4gICAgICAvLyBvciBqdXN0IGhhbmRsZSB0b3VjaCBldmVudFxyXG4gICAgICBldl9jYW52YXMoZSk7XHJcbiAgfSwgZmFsc2UpO1xyXG4gICAgLy9jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgZHJhdywgZmFsc2UpO1xyXG4gICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgZXZfY2FudmFzLCBmYWxzZSk7XHJcbiAgfVxyXG59XHJcblxyXG4vLyBUaGlzIHBhaW50aW5nIHRvb2wgd29ya3MgbGlrZSBhIGRyYXdpbmcgcGVuY2lsIHdoaWNoIHRyYWNrcyB0aGUgbW91c2UgXHJcbi8vIG1vdmVtZW50cy5cclxuZnVuY3Rpb24gdG9vbF9wZW5jaWwoKSB7XHJcbiAgdG9vbCA9IHRoaXM7XHJcbiAgdGhpcy5zdGFydGVkID0gZmFsc2U7XHJcbiAgLy8gVGhpcyBpcyBjYWxsZWQgd2hlbiB5b3Ugc3RhcnQgaG9sZGluZyBkb3duIHRoZSBtb3VzZSBidXR0b24uXHJcbiAgLy8gVGhpcyBzdGFydHMgdGhlIHBlbmNpbCBkcmF3aW5nLlxyXG4gIHRoaXMubW91c2Vkb3duID0gZnVuY3Rpb24gKGV2KSB7XHJcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xyXG4gICAgY29udGV4dC5tb3ZlVG8oZXYuX3gsIGV2Ll95KTtcclxuICAgIHRvb2wuc3RhcnRlZCA9IHRydWU7XHJcbiAgfTtcclxuXHJcbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgZXZlcnkgdGltZSB5b3UgbW92ZSB0aGUgbW91c2UuIE9idmlvdXNseSwgaXQgb25seSBcclxuICAvLyBkcmF3cyBpZiB0aGUgdG9vbC5zdGFydGVkIHN0YXRlIGlzIHNldCB0byB0cnVlICh3aGVuIHlvdSBhcmUgaG9sZGluZyBkb3duIFxyXG4gIC8vIHRoZSBtb3VzZSBidXR0b24pLlxyXG4gIHRoaXMubW91c2Vtb3ZlID0gZnVuY3Rpb24gKGV2KSB7XHJcbiAgICBpZiAodG9vbC5zdGFydGVkKSB7XHJcbiAgICAgIGNvbnRleHQubGluZVRvKGV2Ll94LCBldi5feSk7XHJcbiAgICAgIGNvbnRleHQuc3Ryb2tlKCk7XHJcbiAgICB9XHJcbiAgfTtcclxuXHJcbiAgLy8gVGhpcyBpcyBjYWxsZWQgd2hlbiB5b3UgcmVsZWFzZSB0aGUgbW91c2UgYnV0dG9uLlxyXG4gIHRoaXMubW91c2V1cCA9IGZ1bmN0aW9uIChldikge1xyXG4gICAgaWYgKHRvb2wuc3RhcnRlZCkge1xyXG4gICAgICB0b29sLm1vdXNlbW92ZShldik7XHJcbiAgICAgIHRvb2wuc3RhcnRlZCA9IGZhbHNlO1xyXG4gICAgICBpZihhdXRvU2F2ZSkge1xyXG4gICAgICAgIGNhbnZhc1RvSW1nKCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9O1xyXG59XHJcblxyXG4vLyBUaGUgZ2VuZXJhbC1wdXJwb3NlIGV2ZW50IGhhbmRsZXIuIFRoaXMgZnVuY3Rpb24ganVzdCBkZXRlcm1pbmVzIHRoZSBtb3VzZSBcclxuLy8gcG9zaXRpb24gcmVsYXRpdmUgdG8gdGhlIGNhbnZhcyBlbGVtZW50LlxyXG5mdW5jdGlvbiBldl9jYW52YXMoZXYpIHtcclxuICBpZiAoZXYubGF5ZXJYIHx8IGV2LmxheWVyWCA9PSAwKSB7IC8vIEZpcmVmb3hcclxuICAgIGV2Ll94ID0gZXYubGF5ZXJYO1xyXG4gICAgZXYuX3kgPSBldi5sYXllclk7XHJcbiAgfSBlbHNlIGlmIChldi5vZmZzZXRYIHx8IGV2Lm9mZnNldFggPT0gMCkgeyAvLyBPcGVyYVxyXG4gICAgZXYuX3ggPSBldi5vZmZzZXRYO1xyXG4gICAgZXYuX3kgPSBldi5vZmZzZXRZO1xyXG4gIH0gZWxzZSBpZiggZXYucGFnZVggfHwgIGV2LnBhZ2VYID09IDApIHtcclxuICAgIGV2Ll94ID0gIGV2LnBhZ2VYO1xyXG4gICAgZXYuX3kgPSAgZXYucGFnZVk7XHJcbiAgfVxyXG5cclxuICAvLyBDYWxsIHRoZSBldmVudCBoYW5kbGVyIG9mIHRoZSB0b29sLlxyXG4gIHZhciB0eXBlID0gbnVsbDtcclxuICBzd2l0Y2goZXYudHlwZSl7XHJcbiAgICBjYXNlIFwidG91Y2hzdGFydFwiOlxyXG4gICAgICB0eXBlID0gXCJtb3VzZWRvd25cIjtcclxuICAgICAgYnJlYWs7XHJcbiAgICBjYXNlIFwidG91Y2htb3ZlXCI6XHJcbiAgICAgIHR5cGUgPSBcIm1vdXNlbW92ZVwiO1xyXG4gICAgICBicmVhaztcclxuICAgIGNhc2UgXCJ0b3VjaGVuZFwiOlxyXG4gICAgICB0eXBlID0gXCJtb3VzZXVwXCI7XHJcbiAgICAgIGJyZWFrO1xyXG4gICAgZGVmYXVsdDpcclxuICAgICAgdHlwZSA9IGV2LnR5cGU7XHJcbiAgICAgIGJyZWFrO1xyXG4gIH07XHJcbiAgdmFyIGZ1bmMgPSB0b29sW3R5cGVdO1xyXG4gIGlmIChmdW5jKSB7XHJcbiAgICBmdW5jKGV2KTtcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNhbnZhc0NsZWFyKCkge1xyXG4gIGNvbnN0IGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcclxuICBjb250ZXh0LmNsZWFyUmVjdCgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBjYW52YXNUb0ltZygpIHtcclxuICAvL3ZhciBjYW52YXMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImNhbnZhc1BhaW50ZXJWaWV3XCIpO1xyXG4gIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xyXG4gIC8vZHJhdyBhIHJlZCBib3hcclxuICBjdHguZmlsbFN0eWxlID0gYmFja2dyb3VuZDtcclxuICBjdHguc3Ryb2tlU3R5bGUgPSBjb2xvcjtcclxuICBjdHguZmlsbFJlY3QoMTAsIDEwLCAzMCwgMzApO1xyXG4gIHJldHVybiBjYW52YXMudG9EYXRhVVJMKCk7XHJcbn1cclxuXHJcblxyXG52YXIgZHJhd2VyID0ge1xyXG4gIGlzRHJhd2luZzogZmFsc2UsXHJcbiAgdG91Y2hzdGFydDogZnVuY3Rpb24gKGNvb3JzKSB7XHJcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xyXG4gICAgY29udGV4dC5tb3ZlVG8oY29vcnMueCwgY29vcnMueSk7XHJcbiAgICB0aGlzLmlzRHJhd2luZyA9IHRydWU7XHJcbiAgfSxcclxuICB0b3VjaG1vdmU6IGZ1bmN0aW9uIChjb29ycykge1xyXG4gICAgaWYgKHRoaXMuaXNEcmF3aW5nKSB7XHJcbiAgICAgIGNvbnRleHQubGluZVRvKGNvb3JzLngsIGNvb3JzLnkpO1xyXG4gICAgICBjb250ZXh0LnN0cm9rZSgpO1xyXG4gICAgfVxyXG4gIH0sXHJcbiAgdG91Y2hlbmQ6IGZ1bmN0aW9uIChjb29ycykge1xyXG4gICAgaWYgKHRoaXMuaXNEcmF3aW5nKSB7XHJcbiAgICAgIHRoaXMudG91Y2htb3ZlKGNvb3JzKTtcclxuICAgICAgdGhpcy5pc0RyYXdpbmcgPSBmYWxzZTtcclxuICAgIH1cclxuICB9XHJcbn07XHJcblxyXG5mdW5jdGlvbiBkcmF3KGV2ZW50KSB7XHJcbiAgdmFyIHR5cGUgPSBudWxsO1xyXG4gIHZhciBjb29ycztcclxuICBpZihldmVudC50eXBlID09PSBcInRvdWNoZW5kXCIpIHtcclxuICAgICAgY29vcnMgPSB7XHJcbiAgICAgICAgICB4OiBldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5wYWdlWCxcclxuICAgICAgICAgIHk6IGV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VZXHJcbiAgICAgIH07XHJcbiAgfVxyXG4gIGVsc2Uge1xyXG4gICAgICAvLyBnZXQgdGhlIHRvdWNoIGNvb3JkaW5hdGVzXHJcbiAgICAgIGNvb3JzID0ge1xyXG4gICAgICAgICAgeDogZXZlbnQudG91Y2hlc1swXS5wYWdlWCxcclxuICAgICAgICAgIHk6IGV2ZW50LnRvdWNoZXNbMF0ucGFnZVlcclxuICAgICAgfTtcclxuICB9XHJcbiAgdHlwZSA9IHR5cGUgfHwgZXZlbnQudHlwZVxyXG4gIC8vIHBhc3MgdGhlIGNvb3JkaW5hdGVzIHRvIHRoZSBhcHByb3ByaWF0ZSBoYW5kbGVyXHJcbiAgZHJhd2VyW3R5cGVdKGNvb3JzKTtcclxufSJdfQ==