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
JavaScript
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==