angular2-promise-buttons
Version:
Chilled loading buttons for angular
219 lines • 24.7 kB
JavaScript
import { Directive, HostListener, Inject, Input } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import { DEFAULT_CFG } from './default-promise-btn-config';
import { userCfg } from './user-cfg';
import * as i0 from "@angular/core";
export class PromiseBtnDirective {
constructor(el, cfg) {
// provide configuration
this.cfg = Object.assign({}, DEFAULT_CFG, cfg);
// save element
this.btnEl = el.nativeElement;
}
// this is added to fix the overriding of the disabled state by the loading indicator button.
// https://github.com/johannesjo/angular2-promise-buttons/issues/34
set isDisabledFromTheOutsideSetter(v) {
this.isDisabledFromTheOutside = v;
if (v) {
// disabled means always disabled
this.btnEl.setAttribute('disabled', 'disabled');
}
else if (this.isPromiseDone || this.isPromiseDone === undefined) {
this.btnEl.removeAttribute('disabled');
}
// else the button is loading, so do not change the disabled loading state.
}
set promiseBtn(passedValue) {
const isObservable = passedValue instanceof Observable;
const isSubscription = passedValue instanceof Subscription;
const isBoolean = typeof passedValue === 'boolean';
const isPromise = passedValue instanceof Promise || (passedValue !== null &&
typeof passedValue === 'object' &&
typeof passedValue.then === 'function' &&
typeof passedValue.catch === 'function');
if (isObservable) {
throw new TypeError('promiseBtn must be an instance of Subscription, instance of Observable given');
}
else if (isSubscription) {
const sub = passedValue;
if (!sub.closed) {
this.promise = new Promise((resolve) => {
sub.add(resolve);
});
}
}
else if (isPromise) {
this.promise = passedValue;
}
else if (isBoolean) {
this.promise = this.createPromiseFromBoolean(passedValue);
}
this.checkAndInitPromiseHandler(this.btnEl);
}
ngAfterContentInit() {
this.prepareBtnEl(this.btnEl);
// trigger changes once to handle initial promises
this.checkAndInitPromiseHandler(this.btnEl);
}
ngOnDestroy() {
// cleanup
if (this.minDurationTimeout) {
clearTimeout(this.minDurationTimeout);
}
}
createPromiseFromBoolean(val) {
if (val) {
return new Promise((resolve) => {
this._fakePromiseResolve = resolve;
});
}
else {
if (this._fakePromiseResolve) {
this._fakePromiseResolve();
}
return this.promise;
}
}
/**
* Initializes all html and event handlers
*/
prepareBtnEl(btnEl) {
// handle promises passed via promiseBtn attribute
this.appendSpinnerTpl(btnEl);
}
/**
* Checks if all required parameters are there and inits the promise handler
*/
checkAndInitPromiseHandler(btnEl) {
// check if element and promise is set
if (btnEl && this.promise) {
this.initPromiseHandler(btnEl);
}
}
/**
* Helper FN to add class
*/
addLoadingClass(el) {
if (typeof this.cfg.btnLoadingClass === 'string') {
el.classList.add(this.cfg.btnLoadingClass);
}
}
/**
* Helper FN to remove classes
*/
removeLoadingClass(el) {
if (typeof this.cfg.btnLoadingClass === 'string') {
el.classList.remove(this.cfg.btnLoadingClass);
}
}
/**
* Handles everything to be triggered when the button is set
* to loading state.
*/
initLoadingState(btnEl) {
this.addLoadingClass(btnEl);
this.disableBtn(btnEl);
}
/**
* Handles everything to be triggered when loading is finished
*/
cancelLoadingStateIfPromiseAndMinDurationDone(btnEl) {
if ((!this.cfg.minDuration || this.isMinDurationTimeoutDone) && this.isPromiseDone) {
this.removeLoadingClass(btnEl);
this.enableBtn(btnEl);
}
}
disableBtn(btnEl) {
if (this.cfg.disableBtn) {
btnEl.setAttribute('disabled', 'disabled');
}
}
enableBtn(btnEl) {
if (this.cfg.disableBtn) {
if (this.isDisabledFromTheOutside) {
btnEl.setAttribute('disabled', 'disabled');
}
else {
btnEl.removeAttribute('disabled');
}
}
}
/**
* Initializes a watcher for the promise. Also takes
* this.cfg.minDuration into account if given.
*/
initPromiseHandler(btnEl) {
const promise = this.promise;
// watch promise to resolve or fail
this.isMinDurationTimeoutDone = false;
this.isPromiseDone = false;
// create timeout if option is set
if (this.cfg.minDuration) {
this.minDurationTimeout = window.setTimeout(() => {
this.isMinDurationTimeoutDone = true;
this.cancelLoadingStateIfPromiseAndMinDurationDone(btnEl);
}, this.cfg.minDuration);
}
const resolveLoadingState = () => {
this.isPromiseDone = true;
this.cancelLoadingStateIfPromiseAndMinDurationDone(btnEl);
};
if (!this.cfg.handleCurrentBtnOnly) {
this.initLoadingState(btnEl);
}
// native Promise doesn't have finally
if (promise.finally) {
promise.finally(resolveLoadingState);
}
else {
promise
.then(resolveLoadingState)
.catch(resolveLoadingState);
}
}
/**
* $compile and append the spinner template to the button.
*/
appendSpinnerTpl(btnEl) {
// TODO add some kind of compilation later on
btnEl.insertAdjacentHTML('beforeend', this.cfg.spinnerTpl);
}
/**
* Limit loading state to show only for the currently clicked button.
* Executed only if this.cfg.handleCurrentBtnOnly is set
*/
handleCurrentBtnOnly() {
if (!this.cfg.handleCurrentBtnOnly) {
return true; // return true for testing
}
// Click triggers @Input update
// We need to use timeout to wait for @Input to update
window.setTimeout(() => {
// return if something else than a promise is passed
if (!this.promise) {
return;
}
this.initLoadingState(this.btnEl);
}, 0);
}
}
PromiseBtnDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: PromiseBtnDirective, deps: [{ token: i0.ElementRef }, { token: userCfg }], target: i0.ɵɵFactoryTarget.Directive });
PromiseBtnDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.17", type: PromiseBtnDirective, selector: "[promiseBtn]", inputs: { isDisabledFromTheOutsideSetter: ["disabled", "isDisabledFromTheOutsideSetter"], promiseBtn: "promiseBtn" }, host: { listeners: { "click": "handleCurrentBtnOnly()" } }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: PromiseBtnDirective, decorators: [{
type: Directive,
args: [{
selector: '[promiseBtn]'
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: undefined, decorators: [{
type: Inject,
args: [userCfg]
}] }]; }, propDecorators: { isDisabledFromTheOutsideSetter: [{
type: Input,
args: ['disabled']
}], promiseBtn: [{
type: Input
}], handleCurrentBtnOnly: [{
type: HostListener,
args: ['click']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvbWlzZS1idG4uZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhcjItcHJvbWlzZS1idXR0b25zL3NyYy9wcm9taXNlLWJ0bi5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFtQixTQUFTLEVBQWMsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQVksTUFBTSxlQUFlLENBQUM7QUFDOUcsT0FBTyxFQUFDLFVBQVUsRUFBRSxZQUFZLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDOUMsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLDhCQUE4QixDQUFDO0FBRXpELE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSxZQUFZLENBQUM7O0FBTW5DLE1BQU0sT0FBTyxtQkFBbUI7SUFnQzlCLFlBQVksRUFBYyxFQUNHLEdBQXFCO1FBQ2hELHdCQUF3QjtRQUN4QixJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLFdBQVcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUUvQyxlQUFlO1FBQ2YsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDO0lBQ2hDLENBQUM7SUF6QkQsNkZBQTZGO0lBQzdGLG1FQUFtRTtJQUNuRSxJQUNJLDhCQUE4QixDQUFDLENBQVU7UUFDM0MsSUFBSSxDQUFDLHdCQUF3QixHQUFHLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsRUFBRTtZQUNMLGlDQUFpQztZQUNqQyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7U0FDakQ7YUFBTSxJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTLEVBQUU7WUFDakUsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDeEM7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Q0FBQyxHQUFHLENBQUMsVUFBb0IsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFFRDs7O09BR0c7SUFFSCxvQkFBb0I7UUFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUU7WUFDbEMsT0FBTyxJQUFJLENBQUMsQ0FBQywwQkFBMEI7U0FDeEM7UUFFRCwrQkFBK0I7UUFDL0Isc0RBQXNEO1FBQ3RELE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ3JCLG9EQUFvRDtZQUNwRCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFDakIsT0FBTzthQUNSO1lBRUQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDUixDQUFDOztpSEE1T1UsbUJBQW1CLDRDQWlDVixPQUFPO3FHQWpDaEIsbUJBQW1COzRGQUFuQixtQkFBbUI7a0JBSi9CLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGNBQWM7aUJBQ3pCOzswQkFtQ2MsTUFBTTsyQkFBQyxPQUFPOzRDQWhCdkIsOEJBQThCO3NCQURqQyxLQUFLO3VCQUFDLFVBQVU7Z0JBMEJiLFVBQVU7c0JBRGIsS0FBSztnQkFvTE4sb0JBQW9CO3NCQURuQixZQUFZO3VCQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0FmdGVyQ29udGVudEluaXQsIERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBJbmplY3QsIElucHV0LCBPbkRlc3Ryb3l9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb259IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtERUZBVUxUX0NGR30gZnJvbSAnLi9kZWZhdWx0LXByb21pc2UtYnRuLWNvbmZpZyc7XG5pbXBvcnQge1Byb21pc2VCdG5Db25maWd9IGZyb20gJy4vcHJvbWlzZS1idG4tY29uZmlnJztcbmltcG9ydCB7dXNlckNmZ30gZnJvbSAnLi91c2VyLWNmZyc7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1twcm9taXNlQnRuXSdcbn0pXG5cbmV4cG9ydCBjbGFzcyBQcm9taXNlQnRuRGlyZWN0aXZlIGltcGxlbWVudHMgT25EZXN0cm95LCBBZnRlckNvbnRlbnRJbml0IHtcbiAgY2ZnOiBQcm9taXNlQnRuQ29uZmlnO1xuICAvLyB0aGUgdGltZW91dCB1c2VkIGZvciBtaW4gZHVyYXRpb24gZGlzcGxheVxuICBtaW5EdXJhdGlvblRpbWVvdXQ6IG51bWJlcjtcbiAgLy8gYm9vbGVhbiB0byBkZXRlcm1pbmUgbWluRHVyYXRpb25UaW1lb3V0IHN0YXRlXG4gIGlzTWluRHVyYXRpb25UaW1lb3V0RG9uZTogYm9vbGVhbjtcbiAgLy8gYm9vbGVhbiB0byBkZXRlcm1pbmUgaWYgcHJvbWlzZSB3YXMgcmVzb2x2ZWRcbiAgaXNQcm9taXNlRG9uZTogYm9vbGVhbjtcbiAgLy8gdGhlIHByb21pc2UgYnV0dG9uIGJ1dHRvbiBlbGVtZW50XG4gIGJ0bkVsOiBIVE1MRWxlbWVudDtcbiAgLy8gdGhlIHByb21pc2UgaXRzZWxmIG9yIGEgZnVuY3Rpb24gZXhwcmVzc2lvblxuICAvLyBOT1RFOiB3ZSBuZWVkIHRoZSB0eXBlIGFueSBoZXJlIGFzIHdlIG1pZ2h0IGRlYWwgd2l0aCBjdXN0b20gcHJvbWlzZXMgbGlrZSBibHVlYmlyZFxuICBwcm9taXNlOiBhbnk7XG5cbiAgLy8gdGhpcyBpcyBhZGRlZCB0byBmaXggdGhlIG92ZXJyaWRpbmcgb2YgdGhlIGRpc2FibGVkIHN0YXRlIGJ5IHRoZSBsb2FkaW5nIGluZGljYXRvciBidXR0b24uXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qb2hhbm5lc2pvL2FuZ3VsYXIyLXByb21pc2UtYnV0dG9ucy9pc3N1ZXMvMzRcbiAgQElucHV0KCdkaXNhYmxlZCcpXG4gIHNldCBpc0Rpc2FibGVkRnJvbVRoZU91dHNpZGVTZXR0ZXIodjogYm9vbGVhbikge1xuICAgIHRoaXMuaXNEaXNhYmxlZEZyb21UaGVPdXRzaWRlID0gdjtcbiAgICBpZiAodikge1xuICAgICAgLy8gZGlzYWJsZWQgbWVhbnMgYWx3YXlzIGRpc2FibGVkXG4gICAgICB0aGlzLmJ0bkVsLnNldEF0dHJpYnV0ZSgnZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuaXNQcm9taXNlRG9uZSB8fCB0aGlzLmlzUHJvbWlzZURvbmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5idG5FbC5yZW1vdmVBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gICAgfVxuICAgIC8vIGVsc2UgdGhlIGJ1dHRvbiBpcyBsb2FkaW5nLCBzbyBkbyBub3QgY2hhbmdlIHRoZSBkaXNhYmxlZCBsb2FkaW5nIHN0YXRlLlxuICB9XG5cbiAgaXNEaXNhYmxlZEZyb21UaGVPdXRzaWRlOiBib29sZWFuO1xuXG4gIHByaXZhdGUgX2Zha2VQcm9taXNlUmVzb2x2ZTogKHZhbHVlOiB2b2lkKSA9PiB2b2lkO1xuXG4gIGNvbnN0cnVjdG9yKGVsOiBFbGVtZW50UmVmLFxuICAgICAgICAgICAgICBASW5qZWN0KHVzZXJDZmcpIGNmZzogUHJvbWlzZUJ0bkNvbmZpZykge1xuICAgIC8vIHByb3ZpZGUgY29uZmlndXJhdGlvblxuICAgIHRoaXMuY2ZnID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9DRkcsIGNmZyk7XG5cbiAgICAvLyBzYXZlIGVsZW1lbnRcbiAgICB0aGlzLmJ0bkVsID0gZWwubmF0aXZlRWxlbWVudDtcbiAgfVxuXG4gIEBJbnB1dCgpXG4gIHNldCBwcm9taXNlQnRuKHBhc3NlZFZhbHVlOiBhbnkpIHtcbiAgICBjb25zdCBpc09ic2VydmFibGU6IGJvb2xlYW4gPSBwYXNzZWRWYWx1ZSBpbnN0YW5jZW9mIE9ic2VydmFibGU7XG4gICAgY29uc3QgaXNTdWJzY3JpcHRpb246IGJvb2xlYW4gPSBwYXNzZWRWYWx1ZSBpbnN0YW5jZW9mIFN1YnNjcmlwdGlvbjtcbiAgICBjb25zdCBpc0Jvb2xlYW46IGJvb2xlYW4gPSB0eXBlb2YgcGFzc2VkVmFsdWUgPT09ICdib29sZWFuJztcbiAgICBjb25zdCBpc1Byb21pc2U6IGJvb2xlYW4gPSBwYXNzZWRWYWx1ZSBpbnN0YW5jZW9mIFByb21pc2UgfHwgKFxuICAgICAgcGFzc2VkVmFsdWUgIT09IG51bGwgJiZcbiAgICAgIHR5cGVvZiBwYXNzZWRWYWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHR5cGVvZiBwYXNzZWRWYWx1ZS50aGVuID09PSAnZnVuY3Rpb24nICYmXG4gICAgICB0eXBlb2YgcGFzc2VkVmFsdWUuY2F0Y2ggPT09ICdmdW5jdGlvbidcbiAgICApO1xuXG4gICAgaWYgKGlzT2JzZXJ2YWJsZSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncHJvbWlzZUJ0biBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIFN1YnNjcmlwdGlvbiwgaW5zdGFuY2Ugb2YgT2JzZXJ2YWJsZSBnaXZlbicpO1xuICAgIH0gZWxzZSBpZiAoaXNTdWJzY3JpcHRpb24pIHtcbiAgICAgIGNvbnN0IHN1YjogU3Vic2NyaXB0aW9uID0gcGFzc2VkVmFsdWU7XG4gICAgICBpZiAoIXN1Yi5jbG9zZWQpIHtcbiAgICAgICAgdGhpcy5wcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICBzdWIuYWRkKHJlc29sdmUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzUHJvbWlzZSkge1xuICAgICAgdGhpcy5wcm9taXNlID0gcGFzc2VkVmFsdWU7XG4gICAgfSBlbHNlIGlmIChpc0Jvb2xlYW4pIHtcbiAgICAgIHRoaXMucHJvbWlzZSA9IHRoaXMuY3JlYXRlUHJvbWlzZUZyb21Cb29sZWFuKHBhc3NlZFZhbHVlKTtcbiAgICB9XG5cbiAgICB0aGlzLmNoZWNrQW5kSW5pdFByb21pc2VIYW5kbGVyKHRoaXMuYnRuRWwpO1xuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgIHRoaXMucHJlcGFyZUJ0bkVsKHRoaXMuYnRuRWwpO1xuICAgIC8vIHRyaWdnZXIgY2hhbmdlcyBvbmNlIHRvIGhhbmRsZSBpbml0aWFsIHByb21pc2VzXG4gICAgdGhpcy5jaGVja0FuZEluaXRQcm9taXNlSGFuZGxlcih0aGlzLmJ0bkVsKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIC8vIGNsZWFudXBcbiAgICBpZiAodGhpcy5taW5EdXJhdGlvblRpbWVvdXQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLm1pbkR1cmF0aW9uVGltZW91dCk7XG4gICAgfVxuICB9XG5cbiAgY3JlYXRlUHJvbWlzZUZyb21Cb29sZWFuKHZhbDogYm9vbGVhbik6IFByb21pc2U8YW55PiB7XG4gICAgaWYgKHZhbCkge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIHRoaXMuX2Zha2VQcm9taXNlUmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMuX2Zha2VQcm9taXNlUmVzb2x2ZSkge1xuICAgICAgICB0aGlzLl9mYWtlUHJvbWlzZVJlc29sdmUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLnByb21pc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIGFsbCBodG1sIGFuZCBldmVudCBoYW5kbGVyc1xuICAgKi9cbiAgcHJlcGFyZUJ0bkVsKGJ0bkVsOiBIVE1MRWxlbWVudCkge1xuICAgIC8vIGhhbmRsZSBwcm9taXNlcyBwYXNzZWQgdmlhIHByb21pc2VCdG4gYXR0cmlidXRlXG4gICAgdGhpcy5hcHBlbmRTcGlubmVyVHBsKGJ0bkVsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYWxsIHJlcXVpcmVkIHBhcmFtZXRlcnMgYXJlIHRoZXJlIGFuZCBpbml0cyB0aGUgcHJvbWlzZSBoYW5kbGVyXG4gICAqL1xuICBjaGVja0FuZEluaXRQcm9taXNlSGFuZGxlcihidG5FbDogSFRNTEVsZW1lbnQpIHtcbiAgICAvLyBjaGVjayBpZiBlbGVtZW50IGFuZCBwcm9taXNlIGlzIHNldFxuICAgIGlmIChidG5FbCAmJiB0aGlzLnByb21pc2UpIHtcbiAgICAgIHRoaXMuaW5pdFByb21pc2VIYW5kbGVyKGJ0bkVsKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIEZOIHRvIGFkZCBjbGFzc1xuICAgKi9cbiAgYWRkTG9hZGluZ0NsYXNzKGVsOiBhbnkpIHtcbiAgICBpZiAodHlwZW9mIHRoaXMuY2ZnLmJ0bkxvYWRpbmdDbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVsLmNsYXNzTGlzdC5hZGQodGhpcy5jZmcuYnRuTG9hZGluZ0NsYXNzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIEZOIHRvIHJlbW92ZSBjbGFzc2VzXG4gICAqL1xuICByZW1vdmVMb2FkaW5nQ2xhc3MoZWw6IGFueSkge1xuICAgIGlmICh0eXBlb2YgdGhpcy5jZmcuYnRuTG9hZGluZ0NsYXNzID09PSAnc3RyaW5nJykge1xuICAgICAgZWwuY2xhc3NMaXN0LnJlbW92ZSh0aGlzLmNmZy5idG5Mb2FkaW5nQ2xhc3MpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIGV2ZXJ5dGhpbmcgdG8gYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGJ1dHRvbiBpcyBzZXRcbiAgICogdG8gbG9hZGluZyBzdGF0ZS5cbiAgICovXG4gIGluaXRMb2FkaW5nU3RhdGUoYnRuRWw6IEhUTUxFbGVtZW50KSB7XG4gICAgdGhpcy5hZGRMb2FkaW5nQ2xhc3MoYnRuRWwpO1xuICAgIHRoaXMuZGlzYWJsZUJ0bihidG5FbCk7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyBldmVyeXRoaW5nIHRvIGJlIHRyaWdnZXJlZCB3aGVuIGxvYWRpbmcgaXMgZmluaXNoZWRcbiAgICovXG4gIGNhbmNlbExvYWRpbmdTdGF0ZUlmUHJvbWlzZUFuZE1pbkR1cmF0aW9uRG9uZShidG5FbDogSFRNTEVsZW1lbnQpIHtcbiAgICBpZiAoKCF0aGlzLmNmZy5taW5EdXJhdGlvbiB8fCB0aGlzLmlzTWluRHVyYXRpb25UaW1lb3V0RG9uZSkgJiYgdGhpcy5pc1Byb21pc2VEb25lKSB7XG4gICAgICB0aGlzLnJlbW92ZUxvYWRpbmdDbGFzcyhidG5FbCk7XG4gICAgICB0aGlzLmVuYWJsZUJ0bihidG5FbCk7XG4gICAgfVxuICB9XG5cbiAgZGlzYWJsZUJ0bihidG5FbDogSFRNTEVsZW1lbnQpIHtcbiAgICBpZiAodGhpcy5jZmcuZGlzYWJsZUJ0bikge1xuICAgICAgYnRuRWwuc2V0QXR0cmlidXRlKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgIH1cbiAgfVxuXG4gIGVuYWJsZUJ0bihidG5FbDogSFRNTEVsZW1lbnQpIHtcbiAgICBpZiAodGhpcy5jZmcuZGlzYWJsZUJ0bikge1xuICAgICAgaWYgKHRoaXMuaXNEaXNhYmxlZEZyb21UaGVPdXRzaWRlKSB7XG4gICAgICAgIGJ0bkVsLnNldEF0dHJpYnV0ZSgnZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJ0bkVsLnJlbW92ZUF0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXMgYSB3YXRjaGVyIGZvciB0aGUgcHJvbWlzZS4gQWxzbyB0YWtlc1xuICAgKiB0aGlzLmNmZy5taW5EdXJhdGlvbiBpbnRvIGFjY291bnQgaWYgZ2l2ZW4uXG4gICAqL1xuXG4gIGluaXRQcm9taXNlSGFuZGxlcihidG5FbDogSFRNTEVsZW1lbnQpIHtcbiAgICBjb25zdCBwcm9taXNlID0gdGhpcy5wcm9taXNlO1xuXG4gICAgLy8gd2F0Y2ggcHJvbWlzZSB0byByZXNvbHZlIG9yIGZhaWxcbiAgICB0aGlzLmlzTWluRHVyYXRpb25UaW1lb3V0RG9uZSA9IGZhbHNlO1xuICAgIHRoaXMuaXNQcm9taXNlRG9uZSA9IGZhbHNlO1xuXG4gICAgLy8gY3JlYXRlIHRpbWVvdXQgaWYgb3B0aW9uIGlzIHNldFxuICAgIGlmICh0aGlzLmNmZy5taW5EdXJhdGlvbikge1xuICAgICAgdGhpcy5taW5EdXJhdGlvblRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuaXNNaW5EdXJhdGlvblRpbWVvdXREb25lID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5jYW5jZWxMb2FkaW5nU3RhdGVJZlByb21pc2VBbmRNaW5EdXJhdGlvbkRvbmUoYnRuRWwpO1xuICAgICAgfSwgdGhpcy5jZmcubWluRHVyYXRpb24pO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc29sdmVMb2FkaW5nU3RhdGUgPSAoKSA9PiB7XG4gICAgICB0aGlzLmlzUHJvbWlzZURvbmUgPSB0cnVlO1xuICAgICAgdGhpcy5jYW5jZWxMb2FkaW5nU3RhdGVJZlByb21pc2VBbmRNaW5EdXJhdGlvbkRvbmUoYnRuRWwpO1xuICAgIH07XG5cbiAgICBpZiAoIXRoaXMuY2ZnLmhhbmRsZUN1cnJlbnRCdG5Pbmx5KSB7XG4gICAgICB0aGlzLmluaXRMb2FkaW5nU3RhdGUoYnRuRWwpO1xuICAgIH1cbiAgICAvLyBuYXRpdmUgUHJvbWlzZSBkb2Vzbid0IGhhdmUgZmluYWxseVxuICAgIGlmIChwcm9taXNlLmZpbmFsbHkpIHtcbiAgICAgIHByb21pc2UuZmluYWxseShyZXNvbHZlTG9hZGluZ1N0YXRlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvbWlzZVxuICAgICAgICAudGhlbihyZXNvbHZlTG9hZGluZ1N0YXRlKVxuICAgICAgICAuY2F0Y2gocmVzb2x2ZUxvYWRpbmdTdGF0ZSk7XG4gICAgfVxuXG4gIH1cblxuXG4gIC8qKlxuICAgKiAkY29tcGlsZSBhbmQgYXBwZW5kIHRoZSBzcGlubmVyIHRlbXBsYXRlIHRvIHRoZSBidXR0b24uXG4gICAqL1xuICBhcHBlbmRTcGlubmVyVHBsKGJ0bkVsOiBIVE1MRWxlbWVudCkge1xuICAgIC8vIFRPRE8gYWRkIHNvbWUga2luZCBvZiBjb21waWxhdGlvbiBsYXRlciBvblxuICAgIGJ0bkVsLmluc2VydEFkamFjZW50SFRNTCgnYmVmb3JlZW5kJywgdGhpcy5jZmcuc3Bpbm5lclRwbCBhcyBzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpbWl0IGxvYWRpbmcgc3RhdGUgdG8gc2hvdyBvbmx5IGZvciB0aGUgY3VycmVudGx5IGNsaWNrZWQgYnV0dG9uLlxuICAgKiBFeGVjdXRlZCBvbmx5IGlmIHRoaXMuY2ZnLmhhbmRsZUN1cnJlbnRCdG5Pbmx5IGlzIHNldFxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignY2xpY2snKVxuICBoYW5kbGVDdXJyZW50QnRuT25seSgpIHtcbiAgICBpZiAoIXRoaXMuY2ZnLmhhbmRsZUN1cnJlbnRCdG5Pbmx5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTsgLy8gcmV0dXJuIHRydWUgZm9yIHRlc3RpbmdcbiAgICB9XG5cbiAgICAvLyBDbGljayB0cmlnZ2VycyBASW5wdXQgdXBkYXRlXG4gICAgLy8gV2UgbmVlZCB0byB1c2UgdGltZW91dCB0byB3YWl0IGZvciBASW5wdXQgdG8gdXBkYXRlXG4gICAgd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgLy8gcmV0dXJuIGlmIHNvbWV0aGluZyBlbHNlIHRoYW4gYSBwcm9taXNlIGlzIHBhc3NlZFxuICAgICAgaWYgKCF0aGlzLnByb21pc2UpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmluaXRMb2FkaW5nU3RhdGUodGhpcy5idG5FbCk7XG4gICAgfSwgMCk7XG4gIH1cbn1cbiJdfQ==