ngx-image-uploader
Version:
Angular2 asynchronous image uploader with preview
890 lines (877 loc) • 99.7 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rxjs'), require('@angular/core'), require('@angular/common/http'), require('@angular/forms'), require('cropperjs'), require('@angular/common')) :
typeof define === 'function' && define.amd ? define('ngx-image-uploader', ['exports', 'rxjs', '@angular/core', '@angular/common/http', '@angular/forms', 'cropperjs', '@angular/common'], factory) :
(factory((global['ngx-image-uploader'] = {}),global.rxjs,global.ng.core,global.ng.common.http,global.ng.forms,null,global.ng.common));
}(this, (function (exports,rxjs,i0,i1,forms,Cropper,common) { 'use strict';
Cropper = Cropper && Cropper.hasOwnProperty('default') ? Cropper['default'] : Cropper;
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/** @enum {number} */
var FileQueueStatus = {
Pending: 0,
Success: 1,
Error: 2,
Progress: 3,
};
FileQueueStatus[FileQueueStatus.Pending] = "Pending";
FileQueueStatus[FileQueueStatus.Success] = "Success";
FileQueueStatus[FileQueueStatus.Error] = "Error";
FileQueueStatus[FileQueueStatus.Progress] = "Progress";
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var FileQueueObject = (function () {
function FileQueueObject(file) {
var _this = this;
this.status = FileQueueStatus.Pending;
this.progress = 0;
this.request = null;
this.response = null;
this.isPending = function () { return _this.status === FileQueueStatus.Pending; };
this.isSuccess = function () { return _this.status === FileQueueStatus.Success; };
this.isError = function () { return _this.status === FileQueueStatus.Error; };
this.inProgress = function () { return _this.status === FileQueueStatus.Progress; };
this.isUploadable = function () { return _this.status === FileQueueStatus.Pending || _this.status === FileQueueStatus.Error; };
this.file = file;
}
return FileQueueObject;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var ImageUploaderService = (function () {
function ImageUploaderService(http) {
this.http = http;
}
/**
* @param {?} file
* @param {?} options
* @param {?=} cropOptions
* @return {?}
*/
ImageUploaderService.prototype.uploadFile = /**
* @param {?} file
* @param {?} options
* @param {?=} cropOptions
* @return {?}
*/
function (file, options, cropOptions) {
var _this = this;
this.setDefaults(options);
var /** @type {?} */ form = new FormData();
form.append(options.fieldName, file, file.name);
if (cropOptions) {
form.append('X', cropOptions.x.toString());
form.append('Y', cropOptions.y.toString());
form.append('Width', cropOptions.width.toString());
form.append('Height', cropOptions.height.toString());
}
// upload file and report progress
var /** @type {?} */ req = new i1.HttpRequest('POST', options.uploadUrl, form, {
reportProgress: true,
withCredentials: options.withCredentials,
headers: this._buildHeaders(options)
});
return rxjs.Observable.create(function (obs) {
var /** @type {?} */ queueObj = new FileQueueObject(file);
queueObj.request = _this.http.request(req).subscribe(function (event) {
if (event.type === i1.HttpEventType.UploadProgress) {
_this._uploadProgress(queueObj, event);
obs.next(queueObj);
}
else if (event instanceof i1.HttpResponse) {
_this._uploadComplete(queueObj, event);
obs.next(queueObj);
obs.complete();
}
}, function (err) {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
// A client-side or network error occurred. Handle it accordingly.
_this._uploadFailed(queueObj, err);
obs.next(queueObj);
obs.complete();
}
else {
// The backend returned an unsuccessful response code.
// The backend returned an unsuccessful response code.
_this._uploadFailed(queueObj, err);
obs.next(queueObj);
obs.complete();
}
});
});
};
/**
* @param {?} url
* @param {?} options
* @return {?}
*/
ImageUploaderService.prototype.getFile = /**
* @param {?} url
* @param {?} options
* @return {?}
*/
function (url, options) {
var _this = this;
return rxjs.Observable.create(function (observer) {
var /** @type {?} */ headers = new i1.HttpHeaders();
if (options.authToken) {
headers = headers.append('Authorization', options.authTokenPrefix + " " + options.authToken);
}
_this.http.get(url, { responseType: 'blob', headers: headers }).subscribe(function (res) {
var /** @type {?} */ file = new File([res], 'filename', { type: res.type });
observer.next(file);
observer.complete();
}, function (err) {
observer.error(err.status);
observer.complete();
});
});
};
/**
* @param {?} options
* @return {?}
*/
ImageUploaderService.prototype._buildHeaders = /**
* @param {?} options
* @return {?}
*/
function (options) {
var /** @type {?} */ headers = new i1.HttpHeaders();
if (options.authToken) {
headers = headers.append('Authorization', options.authTokenPrefix + " " + options.authToken);
}
if (options.customHeaders) {
Object.keys(options.customHeaders).forEach(function (key) {
headers = headers.append(key, options.customHeaders[key]);
});
}
return headers;
};
/**
* @param {?} queueObj
* @param {?} event
* @return {?}
*/
ImageUploaderService.prototype._uploadProgress = /**
* @param {?} queueObj
* @param {?} event
* @return {?}
*/
function (queueObj, event) {
// update the FileQueueObject with the current progress
var /** @type {?} */ progress = Math.round(100 * event.loaded / event.total);
queueObj.progress = progress;
queueObj.status = FileQueueStatus.Progress;
// this._queue.next(this._files);
};
/**
* @param {?} queueObj
* @param {?} response
* @return {?}
*/
ImageUploaderService.prototype._uploadComplete = /**
* @param {?} queueObj
* @param {?} response
* @return {?}
*/
function (queueObj, response) {
// update the FileQueueObject as completed
queueObj.progress = 100;
queueObj.status = FileQueueStatus.Success;
queueObj.response = response;
// this._queue.next(this._files);
// this.onCompleteItem(queueObj, response.body);
};
/**
* @param {?} queueObj
* @param {?} response
* @return {?}
*/
ImageUploaderService.prototype._uploadFailed = /**
* @param {?} queueObj
* @param {?} response
* @return {?}
*/
function (queueObj, response) {
// update the FileQueueObject as errored
queueObj.progress = 0;
queueObj.status = FileQueueStatus.Error;
queueObj.response = response;
// this._queue.next(this._files);
};
/**
* @param {?} options
* @return {?}
*/
ImageUploaderService.prototype.setDefaults = /**
* @param {?} options
* @return {?}
*/
function (options) {
options.withCredentials = options.withCredentials || false;
options.httpMethod = options.httpMethod || 'POST';
options.authTokenPrefix = options.authTokenPrefix || 'Bearer';
options.fieldName = options.fieldName || 'file';
};
ImageUploaderService.decorators = [
{ type: i0.Injectable, args: [{
providedIn: 'root'
},] },
];
/** @nocollapse */
ImageUploaderService.ctorParameters = function () {
return [
{ type: i1.HttpClient, },
];
};
/** @nocollapse */ ImageUploaderService.ngInjectableDef = i0.defineInjectable({ factory: function ImageUploaderService_Factory() { return new ImageUploaderService(i0.inject(i1.HttpClient)); }, token: ImageUploaderService, providedIn: "root" });
return ImageUploaderService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @param {?} url
* @param {?} cb
* @return {?}
*/
function createImage(url, cb) {
var /** @type {?} */ image = new Image();
image.onload = function () {
cb(image);
};
image.src = url;
}
var /** @type {?} */ resizeAreaId = 'imageupload-resize-area';
/**
* @return {?}
*/
function getResizeArea() {
var /** @type {?} */ resizeArea = document.getElementById(resizeAreaId);
if (!resizeArea) {
resizeArea = document.createElement('canvas');
resizeArea.id = resizeAreaId;
resizeArea.style.display = 'none';
document.body.appendChild(resizeArea);
}
return /** @type {?} */ (resizeArea);
}
/**
* @param {?} origImage
* @param {?=} __1
* @return {?}
*/
function resizeImage(origImage, _a) {
var _b = _a === void 0 ? {} : _a, resizeHeight = _b.resizeHeight, resizeWidth = _b.resizeWidth, _c = _b.resizeQuality, resizeQuality = _c === void 0 ? 0.7 : _c, _d = _b.resizeType, resizeType = _d === void 0 ? 'image/jpeg' : _d, _e = _b.resizeMode, resizeMode = _e === void 0 ? 'fill' : _e;
var /** @type {?} */ canvas = getResizeArea();
var /** @type {?} */ height = origImage.height;
var /** @type {?} */ width = origImage.width;
var /** @type {?} */ offsetX = 0;
var /** @type {?} */ offsetY = 0;
if (resizeMode === 'fill') {
// calculate the width and height, constraining the proportions
if (width / height > resizeWidth / resizeHeight) {
width = Math.round(height * resizeWidth / resizeHeight);
}
else {
height = Math.round(width * resizeHeight / resizeWidth);
}
canvas.width = resizeWidth <= width ? resizeWidth : width;
canvas.height = resizeHeight <= height ? resizeHeight : height;
offsetX = origImage.width / 2 - width / 2;
offsetY = origImage.height / 2 - height / 2;
// draw image on canvas
var /** @type {?} */ ctx = canvas.getContext('2d');
ctx.drawImage(origImage, offsetX, offsetY, width, height, 0, 0, canvas.width, canvas.height);
}
else if (resizeMode === 'fit') {
// calculate the width and height, constraining the proportions
if (width > height) {
if (width > resizeWidth) {
height = Math.round(height *= resizeWidth / width);
width = resizeWidth;
}
}
else {
if (height > resizeHeight) {
width = Math.round(width *= resizeHeight / height);
height = resizeHeight;
}
}
canvas.width = width;
canvas.height = height;
// draw image on canvas
var /** @type {?} */ ctx = canvas.getContext('2d');
ctx.drawImage(origImage, 0, 0, width, height);
}
else {
throw new Error('Unknown resizeMode: ' + resizeMode);
}
// get the data from canvas as 70% jpg (or specified type).
return canvas.toDataURL(resizeType, resizeQuality);
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/** @enum {number} */
var Status = {
NotSelected: 0,
Selected: 1,
Uploading: 2,
Loading: 3,
Loaded: 4,
Error: 5,
};
Status[Status.NotSelected] = "NotSelected";
Status[Status.Selected] = "Selected";
Status[Status.Uploading] = "Uploading";
Status[Status.Loading] = "Loading";
Status[Status.Loaded] = "Loaded";
Status[Status.Error] = "Error";
var ImageUploaderComponent = (function () {
function ImageUploaderComponent(renderer, uploader, changeDetector) {
this.renderer = renderer;
this.uploader = uploader;
this.changeDetector = changeDetector;
this.statusEnum = Status;
this._status = Status.NotSelected;
this.thumbnailWidth = 150;
this.thumbnailHeight = 150;
this.cropper = undefined;
this.upload = new i0.EventEmitter();
this.statusChange = new i0.EventEmitter();
this.propagateChange = function (_) { };
}
Object.defineProperty(ImageUploaderComponent.prototype, "imageThumbnail", {
get: /**
* @return {?}
*/ function () {
return this._imageThumbnail;
},
set: /**
* @param {?} value
* @return {?}
*/ function (value) {
this._imageThumbnail = value;
this.propagateChange(this._imageThumbnail);
if (value !== undefined) {
this.status = Status.Selected;
}
else {
this.status = Status.NotSelected;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(ImageUploaderComponent.prototype, "errorMessage", {
get: /**
* @return {?}
*/ function () {
return this._errorMessage;
},
set: /**
* @param {?} value
* @return {?}
*/ function (value) {
this._errorMessage = value;
if (value) {
this.status = Status.Error;
}
else {
this.status = Status.NotSelected;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(ImageUploaderComponent.prototype, "status", {
get: /**
* @return {?}
*/ function () {
return this._status;
},
set: /**
* @param {?} value
* @return {?}
*/ function (value) {
this._status = value;
this.statusChange.emit(value);
},
enumerable: true,
configurable: true
});
/**
* @param {?} value
* @return {?}
*/
ImageUploaderComponent.prototype.writeValue = /**
* @param {?} value
* @return {?}
*/
function (value) {
if (value) {
this.loadAndResize(value);
}
else {
this._imageThumbnail = undefined;
this.status = Status.NotSelected;
}
};
/**
* @param {?} fn
* @return {?}
*/
ImageUploaderComponent.prototype.registerOnChange = /**
* @param {?} fn
* @return {?}
*/
function (fn) {
this.propagateChange = fn;
};
/**
* @return {?}
*/
ImageUploaderComponent.prototype.registerOnTouched = /**
* @return {?}
*/
function () { };
/**
* @return {?}
*/
ImageUploaderComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
if (this.options) {
if (this.options.thumbnailWidth) {
this.thumbnailWidth = this.options.thumbnailWidth;
}
if (this.options.thumbnailHeight) {
this.thumbnailHeight = this.options.thumbnailHeight;
}
if (this.options.resizeOnLoad === undefined) {
this.options.resizeOnLoad = true;
}
if (this.options.autoUpload === undefined) {
this.options.autoUpload = true;
}
if (this.options.cropEnabled === undefined) {
this.options.cropEnabled = false;
}
if (this.options.autoUpload && this.options.cropEnabled) {
throw new Error('autoUpload and cropEnabled cannot be enabled simultaneously');
}
}
};
/**
* @return {?}
*/
ImageUploaderComponent.prototype.ngAfterViewChecked = /**
* @return {?}
*/
function () {
if (this.options && this.options.cropEnabled && this.imageElement && this.fileToUpload && !this.cropper) {
this.cropper = new Cropper(this.imageElement.nativeElement, {
viewMode: 1,
aspectRatio: this.options.cropAspectRatio ? this.options.cropAspectRatio : null
});
}
};
/**
* @return {?}
*/
ImageUploaderComponent.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
if (this.cropper) {
this.cropper.destroy();
this.cropper = null;
}
};
/**
* @param {?} url
* @return {?}
*/
ImageUploaderComponent.prototype.loadAndResize = /**
* @param {?} url
* @return {?}
*/
function (url) {
var _this = this;
this.status = Status.Loading;
this.uploader.getFile(url, this.options).subscribe(function (file) {
if (_this.options.resizeOnLoad) {
// thumbnail
var /** @type {?} */ result = {
file: file,
url: URL.createObjectURL(file)
};
_this.resize(result).then(function (r) {
_this._imageThumbnail = r.resized.dataURL;
_this.status = Status.Loaded;
});
}
else {
var /** @type {?} */ result = {
file: null,
url: null
};
_this.fileToDataURL(file, result).then(function (r) {
_this._imageThumbnail = r.dataURL;
_this.status = Status.Loaded;
});
}
}, function (error) {
_this.errorMessage = error || 'Error while getting an image';
});
};
/**
* @return {?}
*/
ImageUploaderComponent.prototype.onImageClicked = /**
* @return {?}
*/
function () {
this.renderer.invokeElementMethod(this.fileInputElement.nativeElement, 'click');
};
/**
* @return {?}
*/
ImageUploaderComponent.prototype.onFileChanged = /**
* @return {?}
*/
function () {
var /** @type {?} */ file = this.fileInputElement.nativeElement.files[0];
if (!file) {
return;
}
this.validateAndUpload(file);
};
/**
* @param {?} file
* @return {?}
*/
ImageUploaderComponent.prototype.validateAndUpload = /**
* @param {?} file
* @return {?}
*/
function (file) {
var _this = this;
this.propagateChange(null);
if (this.options && this.options.allowedImageTypes) {
if (!this.options.allowedImageTypes.some(function (allowedType) { return file.type === allowedType; })) {
this.errorMessage = 'Only these image types are allowed: ' + this.options.allowedImageTypes.join(', ');
return;
}
}
if (this.options && this.options.maxImageSize) {
if (file.size > this.options.maxImageSize * 1024 * 1024) {
this.errorMessage = "Image must not be larger than " + this.options.maxImageSize + " MB";
return;
}
}
this.fileToUpload = file;
if (this.options && this.options.autoUpload) {
this.uploadImage();
}
// thumbnail
var /** @type {?} */ result = {
file: file,
url: URL.createObjectURL(file)
};
this.resize(result).then(function (r) {
_this._imageThumbnail = r.resized.dataURL;
_this.origImageWidth = r.width;
_this.orgiImageHeight = r.height;
if (_this.options && !_this.options.autoUpload) {
_this.status = Status.Selected;
}
});
};
/**
* @return {?}
*/
ImageUploaderComponent.prototype.uploadImage = /**
* @return {?}
*/
function () {
var _this = this;
this.progress = 0;
this.status = Status.Uploading;
var /** @type {?} */ cropOptions;
if (this.cropper) {
var /** @type {?} */ scale = this.origImageWidth / this.cropper.getImageData().naturalWidth;
var /** @type {?} */ cropData = this.cropper.getData();
cropOptions = {
x: Math.round(cropData.x * scale),
y: Math.round(cropData.y * scale),
width: Math.round(cropData.width * scale),
height: Math.round(cropData.height * scale)
};
}
// const queueObj = this.uploader.uploadFile(this.fileToUpload, this.options, cropOptions);
// file progress
this.uploader.uploadFile(this.fileToUpload, this.options, cropOptions).subscribe(function (file) {
_this.progress = file.progress;
if (file.isError()) {
if (file.response.status || file.response.statusText) {
_this.errorMessage = file.response.status + ": " + file.response.statusText;
}
else {
_this.errorMessage = 'Error while uploading';
}
// on some upload errors change detection does not work, so we are forcing manually
// on some upload errors change detection does not work, so we are forcing manually
_this.changeDetector.detectChanges();
}
if (!file.inProgress()) {
// notify that value was changed only when image was uploaded and no error
if (file.isSuccess()) {
_this.propagateChange(_this._imageThumbnail);
_this.status = Status.Selected;
_this.fileToUpload = undefined;
}
_this.upload.emit(file);
}
});
};
/**
* @return {?}
*/
ImageUploaderComponent.prototype.removeImage = /**
* @return {?}
*/
function () {
this.fileInputElement.nativeElement.value = null;
this.imageThumbnail = undefined;
if (this.cropper) {
this.cropper.destroy();
this.cropper = null;
}
};
/**
* @return {?}
*/
ImageUploaderComponent.prototype.dismissError = /**
* @return {?}
*/
function () {
this.errorMessage = undefined;
this.removeImage();
};
/**
* @param {?} e
* @return {?}
*/
ImageUploaderComponent.prototype.drop = /**
* @param {?} e
* @return {?}
*/
function (e) {
e.preventDefault();
e.stopPropagation();
if (!e.dataTransfer || !e.dataTransfer.files.length) {
return;
}
this.validateAndUpload(e.dataTransfer.files[0]);
this.updateDragOverlayStyles(false);
};
/**
* @param {?} e
* @return {?}
*/
ImageUploaderComponent.prototype.dragenter = /**
* @param {?} e
* @return {?}
*/
function (e) {
e.preventDefault();
e.stopPropagation();
};
/**
* @param {?} e
* @return {?}
*/
ImageUploaderComponent.prototype.dragover = /**
* @param {?} e
* @return {?}
*/
function (e) {
e.preventDefault();
e.stopPropagation();
this.updateDragOverlayStyles(true);
};
/**
* @param {?} e
* @return {?}
*/
ImageUploaderComponent.prototype.dragleave = /**
* @param {?} e
* @return {?}
*/
function (e) {
e.preventDefault();
e.stopPropagation();
this.updateDragOverlayStyles(false);
};
/**
* @param {?} isDragOver
* @return {?}
*/
ImageUploaderComponent.prototype.updateDragOverlayStyles = /**
* @param {?} isDragOver
* @return {?}
*/
function (isDragOver) {
// TODO: find a way that does not trigger dragleave when displaying overlay
// if (isDragOver) {
// this.renderer.setElementStyle(this.dragOverlayElement.nativeElement, 'display', 'block');
// } else {
// this.renderer.setElementStyle(this.dragOverlayElement.nativeElement, 'display', 'none');
// }
};
/**
* @param {?} result
* @return {?}
*/
ImageUploaderComponent.prototype.resize = /**
* @param {?} result
* @return {?}
*/
function (result) {
var _this = this;
var /** @type {?} */ resizeOptions = {
resizeHeight: this.thumbnailHeight,
resizeWidth: this.thumbnailWidth,
resizeType: result.file.type,
resizeMode: this.options.thumbnailResizeMode
};
return new Promise(function (resolve) {
createImage(result.url, function (image) {
var /** @type {?} */ dataUrl = resizeImage(image, resizeOptions);
result.width = image.width;
result.height = image.height;
result.resized = {
dataURL: dataUrl,
type: _this.getType(dataUrl)
};
resolve(result);
});
});
};
/**
* @param {?} dataUrl
* @return {?}
*/
ImageUploaderComponent.prototype.getType = /**
* @param {?} dataUrl
* @return {?}
*/
function (dataUrl) {
return dataUrl.match(/:(.+\/.+;)/)[1];
};
/**
* @param {?} file
* @param {?} result
* @return {?}
*/
ImageUploaderComponent.prototype.fileToDataURL = /**
* @param {?} file
* @param {?} result
* @return {?}
*/
function (file, result) {
return new Promise(function (resolve) {
var /** @type {?} */ reader = new FileReader();
reader.onload = function (e) {
result.dataURL = reader.result;
resolve(result);
};
reader.readAsDataURL(file);
});
};
ImageUploaderComponent.decorators = [
{ type: i0.Component, args: [{
selector: 'ngx-image-uploader',
template: "<div class=\"image-container\">\n <div class=\"match-parent\" [ngSwitch]=\"status\">\n\n <div class=\"match-parent\" *ngSwitchCase=\"statusEnum.NotSelected\">\n <button type=\"button\" class=\"add-image-btn\" (click)=\"onImageClicked()\">\n <div>\n <p class=\"plus\">+</p>\n <p>Click here to add image</p>\n <p>Or drop image here</p>\n </div>\n </button>\n </div>\n\n <div class=\"selected-status-wrapper match-parent\" *ngSwitchCase=\"statusEnum.Loaded\">\n <img [src]=\"imageThumbnail\" #imageElement>\n\n <button type=\"button\" class=\"remove\" (click)=\"removeImage()\">\u00D7</button>\n </div>\n\n <div class=\"selected-status-wrapper match-parent\" *ngSwitchCase=\"statusEnum.Selected\">\n <img [src]=\"imageThumbnail\" #imageElement>\n\n <button type=\"button\" class=\"remove\" (click)=\"removeImage()\">\u00D7</button>\n </div>\n\n <div *ngSwitchCase=\"statusEnum.Uploading\">\n <img [attr.src]=\"imageThumbnail ? imageThumbnail : null\" (click)=\"onImageClicked()\">\n\n <div class=\"progress-bar\">\n <div class=\"bar\" [style.width]=\"progress+'%'\"></div>\n </div>\n </div>\n\n <div class=\"match-parent\" *ngSwitchCase=\"statusEnum.Loading\">\n <div class=\"sk-fading-circle\">\n <div class=\"sk-circle1 sk-circle\"></div>\n <div class=\"sk-circle2 sk-circle\"></div>\n <div class=\"sk-circle3 sk-circle\"></div>\n <div class=\"sk-circle4 sk-circle\"></div>\n <div class=\"sk-circle5 sk-circle\"></div>\n <div class=\"sk-circle6 sk-circle\"></div>\n <div class=\"sk-circle7 sk-circle\"></div>\n <div class=\"sk-circle8 sk-circle\"></div>\n <div class=\"sk-circle9 sk-circle\"></div>\n <div class=\"sk-circle10 sk-circle\"></div>\n <div class=\"sk-circle11 sk-circle\"></div>\n <div class=\"sk-circle12 sk-circle\"></div>\n </div>\n </div>\n\n <div class=\"match-parent\" *ngSwitchCase=\"statusEnum.Error\">\n <div class=\"error\">\n <div class=\"error-message\">\n <p>{{errorMessage}}</p>\n </div>\n <button type=\"button\" class=\"remove\" (click)=\"dismissError()\">\u00D7</button>\n </div>\n </div>\n </div>\n\n <input type=\"file\" #fileInput (change)=\"onFileChanged()\">\n <div class=\"drag-overlay\" [hidden]=\"true\" #dragOverlay></div>\n</div>\n",
styles: [":host{display:block}.match-parent{width:100%;height:100%}.add-image-btn{width:100%;height:100%;font-weight:700;opacity:.5;border:0}.add-image-btn:hover{opacity:.7;cursor:pointer;background-color:#ddd;box-shadow:inset 0 0 5px rgba(0,0,0,.3)}.add-image-btn .plus{font-size:30px;font-weight:400;margin-bottom:5px;margin-top:5px}img{cursor:pointer;position:absolute;top:50%;left:50%;margin-right:-50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);max-width:100%}.image-container{width:100%;height:100%;position:relative;display:inline-block;background-color:#f1f1f1;box-shadow:inset 0 0 5px rgba(0,0,0,.2)}.remove{position:absolute;top:0;right:0;width:40px;height:40px;font-size:25px;text-align:center;opacity:.8;border:0;cursor:pointer}.selected-status-wrapper>.remove:hover{opacity:.7;background-color:#fff}.error .remove{opacity:.5}.error .remove:hover{opacity:.7}input{display:none}.error{width:100%;height:100%;border:1px solid #e3a5a2;color:#d2706b;background-color:#fbf1f0;position:relative;text-align:center;display:flex;align-items:center}.error-message{width:100%;line-height:18px}.progress-bar{position:absolute;bottom:10%;left:10%;width:80%;height:5px;background-color:grey;opacity:.9;overflow:hidden}.bar{position:absolute;height:100%;background-color:#a4c639}.drag-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#ff0;opacity:.3}.sk-fading-circle{width:40px;height:40px;position:relative;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.sk-fading-circle .sk-circle{width:100%;height:100%;position:absolute;left:0;top:0}.sk-fading-circle .sk-circle:before{content:'';display:block;margin:0 auto;width:15%;height:15%;background-color:#333;border-radius:100%;-webkit-animation:1.2s ease-in-out infinite both sk-circleFadeDelay;animation:1.2s ease-in-out infinite both sk-circleFadeDelay}.sk-fading-circle .sk-circle2{-webkit-transform:rotate(30deg);transform:rotate(30deg)}.sk-fading-circle .sk-circle3{-webkit-transform:rotate(60deg);transform:rotate(60deg)}.sk-fading-circle .sk-circle4{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.sk-fading-circle .sk-circle5{-webkit-transform:rotate(120deg);transform:rotate(120deg)}.sk-fading-circle .sk-circle6{-webkit-transform:rotate(150deg);transform:rotate(150deg)}.sk-fading-circle .sk-circle7{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.sk-fading-circle .sk-circle8{-webkit-transform:rotate(210deg);transform:rotate(210deg)}.sk-fading-circle .sk-circle9{-webkit-transform:rotate(240deg);transform:rotate(240deg)}.sk-fading-circle .sk-circle10{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.sk-fading-circle .sk-circle11{-webkit-transform:rotate(300deg);transform:rotate(300deg)}.sk-fading-circle .sk-circle12{-webkit-transform:rotate(330deg);transform:rotate(330deg)}.sk-fading-circle .sk-circle2:before{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.sk-fading-circle .sk-circle3:before{-webkit-animation-delay:-1s;animation-delay:-1s}.sk-fading-circle .sk-circle4:before{-webkit-animation-delay:-.9s;animation-delay:-.9s}.sk-fading-circle .sk-circle5:before{-webkit-animation-delay:-.8s;animation-delay:-.8s}.sk-fading-circle .sk-circle6:before{-webkit-animation-delay:-.7s;animation-delay:-.7s}.sk-fading-circle .sk-circle7:before{-webkit-animation-delay:-.6s;animation-delay:-.6s}.sk-fading-circle .sk-circle8:before{-webkit-animation-delay:-.5s;animation-delay:-.5s}.sk-fading-circle .sk-circle9:before{-webkit-animation-delay:-.4s;animation-delay:-.4s}.sk-fading-circle .sk-circle10:before{-webkit-animation-delay:-.3s;animation-delay:-.3s}.sk-fading-circle .sk-circle11:before{-webkit-animation-delay:-.2s;animation-delay:-.2s}.sk-fading-circle .sk-circle12:before{-webkit-animation-delay:-.1s;animation-delay:-.1s}@-webkit-keyframes sk-circleFadeDelay{0%,100%,39%{opacity:0}40%{opacity:1}}@keyframes sk-circleFadeDelay{0%,100%,39%{opacity:0}40%{opacity:1}}"],
host: {
'[style.width]': 'thumbnailWidth + "px"',
'[style.height]': 'thumbnailHeight + "px"'
},
providers: [
{
provide: forms.NG_VALUE_ACCESSOR,
useExisting: i0.forwardRef(function () { return ImageUploaderComponent; }),
multi: true
}
]
},] },
];
/** @nocollapse */
ImageUploaderComponent.ctorParameters = function () {
return [
{ type: i0.Renderer, },
{ type: ImageUploaderService, },
{ type: i0.ChangeDetectorRef, },
];
};
ImageUploaderComponent.propDecorators = {
"imageElement": [{ type: i0.ViewChild, args: ['imageElement',] },],
"fileInputElement": [{ type: i0.ViewChild, args: ['fileInput',] },],
"dragOverlayElement": [{ type: i0.ViewChild, args: ['dragOverlay',] },],
"options": [{ type: i0.Input },],
"upload": [{ type: i0.Output },],
"statusChange": [{ type: i0.Output },],
"drop": [{ type: i0.HostListener, args: ['drop', ['$event'],] },],
"dragenter": [{ type: i0.HostListener, args: ['dragenter', ['$event'],] },],
"dragover": [{ type: i0.HostListener, args: ['dragover', ['$event'],] },],
"dragleave": [{ type: i0.HostListener, args: ['dragleave', ['$event'],] },],
};
return ImageUploaderComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var ImageUploaderModule = (function () {
function ImageUploaderModule() {
}
ImageUploaderModule.decorators = [
{ type: i0.NgModule, args: [{
imports: [
common.CommonModule,
i1.HttpClientModule
],
declarations: [ImageUploaderComponent],
exports: [ImageUploaderComponent]
},] },
];
return ImageUploaderModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
exports.ImageUploaderService = ImageUploaderService;
exports.Status = Status;
exports.ImageUploaderComponent = ImageUploaderComponent;
exports.ImageUploaderModule = ImageUploaderModule;
exports.FileQueueObject = FileQueueObject;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWltYWdlLXVwbG9hZGVyLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vbmd4LWltYWdlLXVwbG9hZGVyL2xpYi9maWxlLXF1ZXVlLW9iamVjdC50cyIsIm5nOi8vbmd4LWltYWdlLXVwbG9hZGVyL2xpYi9pbWFnZS11cGxvYWRlci5zZXJ2aWNlLnRzIiwibmc6Ly9uZ3gtaW1hZ2UtdXBsb2FkZXIvbGliL3V0aWxzLnRzIiwibmc6Ly9uZ3gtaW1hZ2UtdXBsb2FkZXIvbGliL2ltYWdlLXVwbG9hZGVyLmNvbXBvbmVudC50cyIsIm5nOi8vbmd4LWltYWdlLXVwbG9hZGVyL2xpYi9pbWFnZS11cGxvYWRlci5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSHR0cFJlc3BvbnNlLCBIdHRwRXJyb3JSZXNwb25zZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcblxyXG5pbXBvcnQgeyBGaWxlUXVldWVTdGF0dXMgfSBmcm9tICcuL2ZpbGUtcXVldWUtc3RhdHVzJztcclxuXHJcbmV4cG9ydCBjbGFzcyBGaWxlUXVldWVPYmplY3Qge1xyXG4gIHB1YmxpYyBmaWxlOiBhbnk7XHJcbiAgcHVibGljIHN0YXR1czogRmlsZVF1ZXVlU3RhdHVzID0gRmlsZVF1ZXVlU3RhdHVzLlBlbmRpbmc7XHJcbiAgcHVibGljIHByb2dyZXNzOiBudW1iZXIgPSAwO1xyXG4gIHB1YmxpYyByZXF1ZXN0OiBTdWJzY3JpcHRpb24gPSBudWxsO1xyXG4gIHB1YmxpYyByZXNwb25zZTogSHR0cFJlc3BvbnNlPGFueT4gfCBIdHRwRXJyb3JSZXNwb25zZSA9IG51bGw7XHJcblxyXG4gIGNvbnN0cnVjdG9yKGZpbGU6IGFueSkge1xyXG4gICAgdGhpcy5maWxlID0gZmlsZTtcclxuICB9XHJcblxyXG4gIC8vIGFjdGlvbnNcclxuICAvLyBwdWJsaWMgdXBsb2FkID0gKCkgPT4geyAvKiBzZXQgaW4gc2VydmljZSAqLyB9O1xyXG4gIC8vIHB1YmxpYyBjYW5jZWwgPSAoKSA9PiB7IC8qIHNldCBpbiBzZXJ2aWNlICovIH07XHJcbiAgLy8gcHVibGljIHJlbW92ZSA9ICgpID0+IHsgLyogc2V0IGluIHNlcnZpY2UgKi8gfTtcclxuXHJcbiAgLy8gc3RhdHVzZXNcclxuICBwdWJsaWMgaXNQZW5kaW5nID0gKCkgPT4gdGhpcy5zdGF0dXMgPT09IEZpbGVRdWV1ZVN0YXR1cy5QZW5kaW5nO1xyXG4gIHB1YmxpYyBpc1N1Y2Nlc3MgPSAoKSA9PiB0aGlzLnN0YXR1cyA9PT0gRmlsZVF1ZXVlU3RhdHVzLlN1Y2Nlc3M7XHJcbiAgcHVibGljIGlzRXJyb3IgPSAoKSA9PiB0aGlzLnN0YXR1cyA9PT0gRmlsZVF1ZXVlU3RhdHVzLkVycm9yO1xyXG4gIHB1YmxpYyBpblByb2dyZXNzID0gKCkgPT4gdGhpcy5zdGF0dXMgPT09IEZpbGVRdWV1ZVN0YXR1cy5Qcm9ncmVzcztcclxuICBwdWJsaWMgaXNVcGxvYWRhYmxlID0gKCkgPT4gdGhpcy5zdGF0dXMgPT09IEZpbGVRdWV1ZVN0YXR1cy5QZW5kaW5nIHx8IHRoaXMuc3RhdHVzID09PSBGaWxlUXVldWVTdGF0dXMuRXJyb3I7XHJcbn1cclxuIiwiaW1wb3J0IHsgT2JzZXJ2ZXIsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBIdHRwQ2xpZW50LCBIdHRwUmVxdWVzdCwgSHR0cEV2ZW50VHlwZSwgSHR0cFJlc3BvbnNlLCBIdHRwRXJyb3JSZXNwb25zZSwgSHR0cEhlYWRlcnMgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcblxyXG5pbXBvcnQgeyBGaWxlUXVldWVPYmplY3QgfSBmcm9tICcuL2ZpbGUtcXVldWUtb2JqZWN0JztcclxuaW1wb3J0IHsgRmlsZVF1ZXVlU3RhdHVzIH0gZnJvbSAnLi9maWxlLXF1ZXVlLXN0YXR1cyc7XHJcbmltcG9ydCB7IEZpbGVVcGxvYWRlck9wdGlvbnMsIENyb3BPcHRpb25zIH0gZnJvbSAnLi9pbnRlcmZhY2VzJztcclxuXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCdcclxufSlcclxuZXhwb3J0IGNsYXNzIEltYWdlVXBsb2FkZXJTZXJ2aWNlIHtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50KSB7fVxyXG5cclxuICB1cGxvYWRGaWxlKGZpbGU6IEZpbGUsIG9wdGlvbnM6IEZpbGVVcGxvYWRlck9wdGlvbnMsIGNyb3BPcHRpb25zPzogQ3JvcE9wdGlvbnMpOiBPYnNlcnZhYmxlPEZpbGVRdWV1ZU9iamVjdD4ge1xyXG4gICAgdGhpcy5zZXREZWZhdWx0cyhvcHRpb25zKTtcclxuXHJcbiAgICBjb25zdCBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XHJcbiAgICBmb3JtLmFwcGVuZChvcHRpb25zLmZpZWxkTmFtZSwgZmlsZSwgZmlsZS5uYW1lKTtcclxuXHJcbiAgICBpZiAoY3JvcE9wdGlvbnMpIHtcclxuICAgICAgZm9ybS5hcHBlbmQoJ1gnLCBjcm9wT3B0aW9ucy54LnRvU3RyaW5nKCkpO1xyXG4gICAgICBmb3JtLmFwcGVuZCgnWScsIGNyb3BPcHRpb25zLnkudG9TdHJpbmcoKSk7XHJcbiAgICAgIGZvcm0uYXBwZW5kKCdXaWR0aCcsIGNyb3BPcHRpb25zLndpZHRoLnRvU3RyaW5nKCkpO1xyXG4gICAgICBmb3JtLmFwcGVuZCgnSGVpZ2h0JywgY3JvcE9wdGlvbnMuaGVpZ2h0LnRvU3RyaW5nKCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHVwbG9hZCBmaWxlIGFuZCByZXBvcnQgcHJvZ3Jlc3NcclxuICAgIGNvbnN0IHJlcSA9IG5ldyBIdHRwUmVxdWVzdCgnUE9TVCcsIG9wdGlvbnMudXBsb2FkVXJsLCBmb3JtLCB7XHJcbiAgICAgIHJlcG9ydFByb2dyZXNzOiB0cnVlLFxyXG4gICAgICB3aXRoQ3JlZGVudGlhbHM6IG9wdGlvbnMud2l0aENyZWRlbnRpYWxzLFxyXG4gICAgICBoZWFkZXJzOiB0aGlzLl9idWlsZEhlYWRlcnMob3B0aW9ucylcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShvYnMgPT4ge1xyXG4gICAgICBjb25zdCBxdWV1ZU9iaiA9IG5ldyBGaWxlUXVldWVPYmplY3QoZmlsZSk7XHJcblxyXG4gICAgICBxdWV1ZU9iai5yZXF1ZXN0ID0gdGhpcy5odHRwLnJlcXVlc3QocmVxKS5zdWJzY3JpYmUoXHJcbiAgICAgICAgKGV2ZW50OiBhbnkpID0+IHtcclxuICAgICAgICAgIGlmIChldmVudC50eXBlID09PSBIdHRwRXZlbnRUeXBlLlVwbG9hZFByb2dyZXNzKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3VwbG9hZFByb2dyZXNzKHF1ZXVlT2JqLCBldmVudCk7XHJcbiAgICAgICAgICAgIG9icy5uZXh0KHF1ZXVlT2JqKTtcclxuICAgICAgICAgIH0gZWxzZSBpZiAoZXZlbnQgaW5zdGFuY2VvZiBIdHRwUmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgdGhpcy5fdXBsb2FkQ29tcGxldGUocXVldWVPYmosIGV2ZW50KTtcclxuICAgICAgICAgICAgb2JzLm5leHQocXVldWVPYmopO1xyXG4gICAgICAgICAgICBvYnMuY29tcGxldGUoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIChlcnI6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgICBpZiAoZXJyLmVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcclxuICAgICAgICAgICAgLy8gQSBjbGllbnQtc2lkZSBvciBuZXR3b3JrIGVycm9yIG9jY3VycmVkLiBIYW5kbGUgaXQgYWNjb3JkaW5nbHkuXHJcbiAgICAgICAgICAgIHRoaXMuX3VwbG9hZEZhaWxlZChxdWV1ZU9iaiwgZXJyKTtcclxuICAgICAgICAgICAgb2JzLm5leHQocXVldWVPYmopO1xyXG4gICAgICAgICAgICBvYnMuY29tcGxldGUoKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIFRoZSBiYWNrZW5kIHJldHVybmVkIGFuIHVuc3VjY2Vzc2Z1bCByZXNwb25zZSBjb2RlLlxyXG4gICAgICAgICAgICB0aGlzLl91cGxvYWRGYWlsZWQocXVldWVPYmosIGVycik7XHJcbiAgICAgICAgICAgIG9icy5uZXh0KHF1ZXVlT2JqKTtcclxuICAgICAgICAgICAgb2JzLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBnZXRGaWxlKHVybDogc3RyaW5nLCBvcHRpb25zOiB7IGF1dGhUb2tlbj86IHN0cmluZywgYXV0aFRva2VuUHJlZml4Pzogc3RyaW5nIH0pOiBPYnNlcnZhYmxlPEZpbGU+IHtcclxuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZSgob2JzZXJ2ZXI6IE9ic2VydmVyPEZpbGU+KSA9PiB7XHJcbiAgICAgIGxldCBoZWFkZXJzID0gbmV3IEh0dHBIZWFkZXJzKCk7XHJcblxyXG4gICAgICBpZiAob3B0aW9ucy5hdXRoVG9rZW4pIHtcclxuICAgICAgICBoZWFkZXJzID0gaGVhZGVycy5hcHBlbmQoJ0F1dGhvcml6YXRpb24nLCBgJHtvcHRpb25zLmF1dGhUb2tlblByZWZpeH0gJHtvcHRpb25zLmF1dGhUb2tlbn1gKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5odHRwLmdldCh1cmwsIHsgcmVzcG9uc2VUeXBlOiAnYmxvYicsIGhlYWRlcnM6IGhlYWRlcnN9KS5zdWJzY3JpYmUocmVzID0+IHtcclxuICAgICAgICBjb25zdCBmaWxlID0gbmV3IEZpbGUoW3Jlc10sICdmaWxlbmFtZScsIHsgdHlwZTogcmVzLnR5cGUgfSk7XHJcbiAgICAgICAgb2JzZXJ2ZXIubmV4dChmaWxlKTtcclxuICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xyXG4gICAgICB9LCBlcnIgPT4ge1xyXG4gICAgICAgIG9ic2VydmVyLmVycm9yKGVyci5zdGF0dXMpO1xyXG4gICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9idWlsZEhlYWRlcnMob3B0aW9uczogRmlsZVVwbG9hZGVyT3B0aW9ucyk6IEh0dHBIZWFkZXJzIHtcclxuICAgIGxldCBoZWFkZXJzID0gbmV3IEh0dHBIZWFkZXJzKCk7XHJcblxyXG4gICAgaWYgKG9wdGlvbnMuYXV0aFRva2VuKSB7XHJcbiAgICAgIGhlYWRlcnMgPSBoZWFkZXJzLmFwcGVuZCgnQXV0aG9yaXphdGlvbicsIGAke29wdGlvbnMuYXV0aFRva2VuUHJlZml4fSAke29wdGlvbnMuYXV0aFRva2VufWApO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChvcHRpb25zLmN1c3RvbUhlYWRlcnMpIHtcclxuICAgICAgT2JqZWN0LmtleXMob3B0aW9ucy5jdXN0b21IZWFkZXJzKS5mb3JFYWNoKChrZXkpID0+IHtcclxuICAgICAgICBoZWFkZXJzID0gaGVhZGVycy5hcHBlbmQoa2V5LCBvcHRpb25zLmN1c3RvbUhlYWRlcnNba2V5XSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBoZWFkZXJzO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfdXBsb2FkUHJvZ3Jlc3MocXVldWVPYmo6IEZpbGVRdWV1ZU9iamVjdCwgZXZlbnQ6IGFueSkge1xyXG4gICAgLy8gdXBkYXRlIHRoZSBGaWxlUXVldWVPYmplY3Qgd2l0aCB0aGUgY3VycmVudCBwcm9ncmVzc1xyXG4gICAgY29uc3QgcHJvZ3Jlc3MgPSBNYXRoLnJvdW5kKDEwMCAqIGV2ZW50LmxvYWRlZCAvIGV2ZW50LnRvdGFsKTtcclxuICAgIHF1ZXVlT2JqLnByb2dyZXNzID0gcHJvZ3Jlc3M7XHJcbiAgICBxdWV1ZU9iai5zdGF0dXMgPSBGaWxlUXVldWVTdGF0dXMuUHJvZ3Jlc3M7XHJcbiAgICAvLyB0aGlzLl9xdWV1ZS5uZXh0KHRoaXMuX2ZpbGVzKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX3VwbG9hZENvbXBsZXRlKHF1ZXVlT2JqOiBGaWxlUXVldWVPYmplY3QsIHJlc3BvbnNlOiBIdHRwUmVzcG9uc2U8YW55Pikge1xyXG4gICAgLy8gdXBkYXRlIHRoZSBGaWxlUXVldWVPYmplY3QgYXMgY29tcGxldGVkXHJcbiAgICBxdWV1ZU9iai5wcm9ncmVzcyA9IDEwMDtcclxuICAgIHF1ZXVlT2JqLnN0YXR1cyA9IEZpbGVRdWV1ZVN0YXR1cy5TdWNjZXNzO1xyXG4gICAgcXVldWVPYmoucmVzcG9uc2UgPSByZXNwb25zZTtcclxuICAgIC8vIHRoaXMuX3F1ZXVlLm5leHQodGhpcy5fZmlsZXMpO1xyXG4gICAgLy8gdGhpcy5vbkNvbXBsZXRlSXRlbShxdWV1ZU9iaiwgcmVzcG9uc2UuYm9keSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF91cGxvYWRGYWlsZWQocXVldWVPYmo6IEZpbGVRdWV1ZU9iamVjdCwgcmVzcG9uc2U6IEh0dHBFcnJvclJlc3BvbnNlKSB7XHJcbiAgICAvLyB1cGRhdGUgdGhlIEZpbGVRdWV1ZU9iamVjdCBhcyBlcnJvcmVkXHJcbiAgICBxdWV1ZU9iai5wcm9ncmVzcyA9IDA7XHJcbiAgICBxdWV1ZU9iai5zdGF0dXMgPSBGaWxlUXVldWVTdGF0dXMuRXJyb3I7XHJcbiAgICBxdWV1ZU9iai5yZXNwb25zZSA9IHJlc3BvbnNlO1xyXG4gICAgLy8gdGhpcy5fcXVldWUubmV4dCh0aGlzLl9maWxlcyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldERlZmF1bHRzKG9wdGlvbnM6IEZpbGVVcGxvYWRlck9wdGlvbnMpIHtcclxuICAgIG9wdGlvbnMud2l0aENyZWRlbnRpYWxzID0gb3B0aW9ucy53aXRoQ3JlZGVudGlhbHMgfHwgZmFsc2U7XHJcbiAgICBvcHRpb25zLmh0dHBNZXRob2QgPSBvcHRpb25zLmh0dHBNZXRob2QgfHwgJ1BPU1QnO1xyXG4gICAgb3B0aW9ucy5hdXRoVG9rZW5QcmVmaXggPSBvcHRpb25zLmF1dGhUb2tlblByZWZpeCB8fCAnQmVhcmVyJztcclxuICA