ngx-parallax-scroll
Version:
This is a simple angular plugin, that allows us to implement parallax effect for some element in page
427 lines • 31.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Directive, ElementRef, Renderer2, Input, Inject, PLATFORM_ID } from '@angular/core';
import { isDevMode } from '@angular/core';
import { isPlatformServer } from '@angular/common';
import { fromEvent } from 'rxjs';
import { throttleTime } from 'rxjs/operators';
var ParallaxScrollDirective = /** @class */ (function () {
function ParallaxScrollDirective(elem, renderer, platformId) {
this.elem = elem;
this.renderer = renderer;
this.platformId = platformId;
this._parallaxTimingFunVal = 'linear';
this._parallaxThrottleTime = 0;
this.directiveName = this.constructor.name;
}
/**
* @return {?}
*/
ParallaxScrollDirective.prototype.ngOnInit = /**
* @return {?}
*/
function () {
if (isPlatformServer(this.platformId))
return;
// Initing parallax effect and setting element styles
this.initParallax();
this.setParallaxElTransform();
this.setParallaxTransition();
};
/**
* @param {?} changes
* @return {?}
*/
ParallaxScrollDirective.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
// Setting parallax options from config object or input props
/** @type {?} */
var prlxSpeed = (changes['parallaxSpeed'] && changes['parallaxSpeed'].currentValue) ||
(changes['config'] && changes['config'].currentValue.parallaxSpeed);
/** @type {?} */
var prlxSmoothness = (changes['parallaxSmoothness'] && changes['parallaxSmoothness'].currentValue) ||
(changes['config'] && changes['config'].currentValue.parallaxSmoothness);
/** @type {?} */
var prlxDirection = (changes['parallaxDirection'] && changes['parallaxDirection'].currentValue) ||
(changes['config'] && changes['config'].currentValue.parallaxDirection);
/** @type {?} */
var prlxTimingFunction = (changes['parallaxTimingFunction'] && changes['parallaxTimingFunction'].currentValue) ||
(changes['config'] && changes['config'].currentValue.parallaxTimingFunction);
/** @type {?} */
var prlxThrottleTime = (changes['parallaxThrottleTime'] && changes['parallaxThrottleTime'].currentValue) ||
(changes['config'] && changes['config'].currentValue.parallaxThrottleTime);
this.setParallaxSpeed(prlxSpeed);
this.setParallaxSmoothness(prlxSmoothness);
this.setParallaxDirection(prlxDirection);
this.setParallaxTimingFun(prlxTimingFunction);
this.setParallaxThrottleTime(prlxThrottleTime);
};
/**
* @return {?}
*/
ParallaxScrollDirective.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () { };
/**
* @return {?}
*/
ParallaxScrollDirective.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.scrollSubscribtion && this.scrollSubscribtion.unsubscribe();
};
// Setting parallax effect and setting element styles
// Setting parallax effect and setting element styles
/**
* @return {?}
*/
ParallaxScrollDirective.prototype.initParallax =
// Setting parallax effect and setting element styles
/**
* @return {?}
*/
function () {
var _this = this;
this.scrollSubscribtion = fromEvent(window, 'scroll')
.pipe(throttleTime(this.prlxThrottleTime))
.subscribe((/**
* @return {?}
*/
function () {
_this.setParallaxElTransform();
}));
};
// Setting parallax speed effect styles
// Setting parallax speed effect styles
/**
* @return {?}
*/
ParallaxScrollDirective.prototype.setParallaxElTransform =
// Setting parallax speed effect styles
/**
* @return {?}
*/
function () {
/** @type {?} */
var scrolled = window.pageYOffset;
this.renderer.setStyle(this.elem.nativeElement, 'transform', "translateY(" + scrolled * this.prlxSpeed + "px) translateZ(0)");
};
// Setting parallax smooth effect styles, based on CSS animation-timing-function
// Setting parallax smooth effect styles, based on CSS animation-timing-function
/**
* @return {?}
*/
ParallaxScrollDirective.prototype.setParallaxTransition =
// Setting parallax smooth effect styles, based on CSS animation-timing-function
/**
* @return {?}
*/
function () {
this.renderer.setStyle(this.elem.nativeElement, 'transition', "transform " + this.prlxSmoothness + "s " + this.prlxTimingFun);
};
// Setting parallax properties
// Setting parallax properties
/**
* @param {?} speedVal
* @return {?}
*/
ParallaxScrollDirective.prototype.setParallaxSpeed =
// Setting parallax properties
/**
* @param {?} speedVal
* @return {?}
*/
function (speedVal) {
/** @type {?} */
var propName = 'parallaxSpeed';
this.validateParallaxSpeed(speedVal, propName, 'number') && (this._parallaxSpeedVal = speedVal);
};
/**
* @param {?} smoothnessVal
* @return {?}
*/
ParallaxScrollDirective.prototype.setParallaxSmoothness = /**
* @param {?} smoothnessVal
* @return {?}
*/
function (smoothnessVal) {
/** @type {?} */
var propName = 'parallaxSmoothness';
this.validateParallaxSmoothness(smoothnessVal, propName, 'number') &&
(this._parallaxSmoothnessVal = smoothnessVal);
};
/**
* @param {?} directionVal
* @return {?}
*/
ParallaxScrollDirective.prototype.setParallaxDirection = /**
* @param {?} directionVal
* @return {?}
*/
function (directionVal) {
/** @type {?} */
var propName = 'parallaxDirection';
directionVal &&
this.isTypeOf(directionVal, 'string', propName) &&
directionVal === 'reverse' &&
(this._parallaxSpeedVal *= -1);
};
/**
* @param {?} timingFun
* @return {?}
*/
ParallaxScrollDirective.prototype.setParallaxTimingFun = /**
* @param {?} timingFun
* @return {?}
*/
function (timingFun) {
/** @type {?} */
var propName = 'parallaxTimingFunction';
timingFun &&
this.isTypeOf(timingFun, 'string', propName) &&
(this._parallaxTimingFunVal = timingFun);
};
/**
* @param {?} throttleTime
* @return {?}
*/
ParallaxScrollDirective.prototype.setParallaxThrottleTime = /**
* @param {?} throttleTime
* @return {?}
*/
function (throttleTime) {
/** @type {?} */
var propName = 'parallaxThrottleTime';
throttleTime &&
this.isTypeOf(throttleTime, 'number', propName) &&
(this._parallaxThrottleTime = throttleTime);
};
Object.defineProperty(ParallaxScrollDirective.prototype, "prlxSpeed", {
// Getters for parallax options
get:
// Getters for parallax options
/**
* @return {?}
*/
function () {
return this._parallaxSpeedVal;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ParallaxScrollDirective.prototype, "prlxSmoothness", {
get: /**
* @return {?}
*/
function () {
return this._parallaxSmoothnessVal;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ParallaxScrollDirective.prototype, "prlxTimingFun", {
get: /**
* @return {?}
*/
function () {
return this._parallaxTimingFunVal;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ParallaxScrollDirective.prototype, "prlxThrottleTime", {
get: /**
* @return {?}
*/
function () {
return this._parallaxThrottleTime;
},
enumerable: true,
configurable: true
});
// Validation functions
// Validation functions
/**
* @param {?} value
* @param {?} propName
* @return {?}
*/
ParallaxScrollDirective.prototype.isProvided =
// Validation functions
/**
* @param {?} value
* @param {?} propName
* @return {?}
*/
function (value, propName) {
/** @type {?} */
var isNotProvided = value == null || value === '';
if (isNotProvided && isDevMode()) {
throw new Error(this.directiveName + ": @Input [" + propName + "] is required, but was not provided");
}
return true;
};
/**
* @param {?} value
* @param {?} requiredType
* @param {?} propName
* @return {?}
*/
ParallaxScrollDirective.prototype.isTypeOf = /**
* @param {?} value
* @param {?} requiredType
* @param {?} propName
* @return {?}
*/
function (value, requiredType, propName) {
/** @type {?} */
var isRequiredType = typeof value === requiredType;
if (!isRequiredType && isDevMode()) {
throw new Error(this.directiveName + ": @Input [" + propName + "] is expected to be of type '" + requiredType + "', but type '" + typeof value + "' was provided");
}
return true;
};
/**
* @param {?} value
* @param {?} propName
* @return {?}
*/
ParallaxScrollDirective.prototype.isPositive = /**
* @param {?} value
* @param {?} propName
* @return {?}
*/
function (value, propName) {
/** @type {?} */
var isRequiredType = typeof value === 'number';
/** @type {?} */
var isValid = value >= 0;
if (isRequiredType && !isValid && isDevMode()) {
throw new Error(this.directiveName + ": @Input [" + propName + "] is expected to be positive value, but negative '" + value + "' value was provided");
}
return true;
};
// Executing validation functions to validate parallax speed
// Executing validation functions to validate parallax speed
/**
* @param {?} value
* @param {?} propName
* @param {?} requiredType
* @return {?}
*/
ParallaxScrollDirective.prototype.validateParallaxSpeed =
// Executing validation functions to validate parallax speed
/**
* @param {?} value
* @param {?} propName
* @param {?} requiredType
* @return {?}
*/
function (value, propName, requiredType) {
return (this.isProvided(value, propName) &&
this.isTypeOf(value, requiredType, propName) &&
this.isPositive(value, propName));
};
// Executing validation functions to validate parallax smoothness
// Executing validation functions to validate parallax smoothness
/**
* @param {?} value
* @param {?} propName
* @param {?} requiredType
* @return {?}
*/
ParallaxScrollDirective.prototype.validateParallaxSmoothness =
// Executing validation functions to validate parallax smoothness
/**
* @param {?} value
* @param {?} propName
* @param {?} requiredType
* @return {?}
*/
function (value, propName, requiredType) {
return (this.isProvided(value, propName) &&
this.isTypeOf(value, requiredType, propName) &&
this.isPositive(value, propName));
};
ParallaxScrollDirective.decorators = [
{ type: Directive, args: [{
selector: '[ngxParallaxScroll]'
},] }
];
/** @nocollapse */
ParallaxScrollDirective.ctorParameters = function () { return [
{ type: ElementRef },
{ type: Renderer2 },
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
]; };
ParallaxScrollDirective.propDecorators = {
config: [{ type: Input }],
parallaxSpeed: [{ type: Input }],
parallaxSmoothness: [{ type: Input }],
parallaxDirection: [{ type: Input }],
parallaxTimingFunction: [{ type: Input }],
parallaxThrottleTime: [{ type: Input }]
};
return ParallaxScrollDirective;
}());
export { ParallaxScrollDirective };
if (false) {
/**
* @type {?}
* @private
*/
ParallaxScrollDirective.prototype.config;
/** @type {?} */
ParallaxScrollDirective.prototype.parallaxSpeed;
/** @type {?} */
ParallaxScrollDirective.prototype.parallaxSmoothness;
/** @type {?} */
ParallaxScrollDirective.prototype.parallaxDirection;
/** @type {?} */
ParallaxScrollDirective.prototype.parallaxTimingFunction;
/** @type {?} */
ParallaxScrollDirective.prototype.parallaxThrottleTime;
/**
* @type {?}
* @private
*/
ParallaxScrollDirective.prototype._parallaxSpeedVal;
/**
* @type {?}
* @private
*/
ParallaxScrollDirective.prototype._parallaxSmoothnessVal;
/**
* @type {?}
* @private
*/
ParallaxScrollDirective.prototype._parallaxTimingFunVal;
/**
* @type {?}
* @private
*/
ParallaxScrollDirective.prototype._parallaxThrottleTime;
/** @type {?} */
ParallaxScrollDirective.prototype.scrollSubscribtion;
/** @type {?} */
ParallaxScrollDirective.prototype.isPrxElInViewport;
/** @type {?} */
ParallaxScrollDirective.prototype.directiveName;
/** @type {?} */
ParallaxScrollDirective.prototype.elem;
/** @type {?} */
ParallaxScrollDirective.prototype.renderer;
/**
* @type {?}
* @private
*/
ParallaxScrollDirective.prototype.platformId;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXBhcmFsbGF4LXNjcm9sbC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtcGFyYWxsYXgtc2Nyb2xsLyIsInNvdXJjZXMiOlsibGliL25neC1wYXJhbGxheC1zY3JvbGwuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFVBQVUsRUFDVixTQUFTLEVBQ1QsS0FBSyxFQU1MLE1BQU0sRUFDTixXQUFXLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsU0FBUyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHOUM7SUFnQ0UsaUNBQ1MsSUFBZ0IsRUFDaEIsUUFBbUIsRUFDRyxVQUFrQjtRQUZ4QyxTQUFJLEdBQUosSUFBSSxDQUFZO1FBQ2hCLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDRyxlQUFVLEdBQVYsVUFBVSxDQUFRO1FBVnpDLDBCQUFxQixHQUFXLFFBQVEsQ0FBQztRQUN6QywwQkFBcUIsR0FBVyxDQUFDLENBQUM7UUFJMUMsa0JBQWEsR0FBVyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQztJQU0zQyxDQUFDOzs7O0lBRUosMENBQVE7OztJQUFSO1FBQ0UsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO1lBQUUsT0FBTztRQUU5QyxxREFBcUQ7UUFDckQsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQy9CLENBQUM7Ozs7O0lBRUQsNkNBQVc7Ozs7SUFBWCxVQUFZLE9BQXNC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QW1Ea0MsTUFBTSx1QkFBOUMsTUFBTSxTQUFDLFdBQVc7Ozt5QkE5QnBCLEtBQUs7Z0NBRUwsS0FBSztxQ0FHTCxLQUFLO29DQUdMLEtBQUs7eUNBR0wsS0FBSzt1Q0FHTCxLQUFLOztJQTRNUiw4QkFBQztDQUFBLEFBL05ELElBK05DO1NBNU5ZLHVCQUF1Qjs7Ozs7O0lBRWxDLHlDQUFnRDs7SUFFaEQsZ0RBQ3NCOztJQUV0QixxREFDMkI7O0lBRTNCLG9EQUNzQzs7SUFFdEMseURBQ2dDOztJQUVoQyx1REFDOEI7Ozs7O0lBRzlCLG9EQUFrQzs7Ozs7SUFDbEMseURBQXVDOzs7OztJQUN2Qyx3REFBaUQ7Ozs7O0lBQ2pELHdEQUEwQzs7SUFFMUMscURBQWlDOztJQUNqQyxvREFBMkI7O0lBQzNCLGdEQUE4Qzs7SUFHNUMsdUNBQXVCOztJQUN2QiwyQ0FBMEI7Ozs7O0lBQzFCLDZDQUErQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgUmVuZGVyZXIyLFxuICBJbnB1dCxcbiAgT25Jbml0LFxuICBBZnRlclZpZXdJbml0LFxuICBPbkNoYW5nZXMsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgSW5qZWN0LFxuICBQTEFURk9STV9JRFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGlzRGV2TW9kZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybVNlcnZlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBmcm9tRXZlbnQsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGhyb3R0bGVUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSVBhcmFsbGF4U2Nyb2xsQ29uZmlnLCBQYXJhbGxheERpcmVjdGlvbiB9IGZyb20gJy4vbmd4LXBhcmFsbGF4LmludGVyZmFjZXMnO1xuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbbmd4UGFyYWxsYXhTY3JvbGxdJ1xufSlcbmV4cG9ydCBjbGFzcyBQYXJhbGxheFNjcm9sbERpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICAvLyBSZXF1aXJlZCBpbnB1dCBmcm9tIGNvbmZpZyBvYmplY3Qgb3IgaW5wdXQgcHJvcHNcbiAgQElucHV0KCkgcHJpdmF0ZSBjb25maWc/OiBJUGFyYWxsYXhTY3JvbGxDb25maWc7XG5cbiAgQElucHV0KClcbiAgcGFyYWxsYXhTcGVlZDogbnVtYmVyO1xuXG4gIEBJbnB1dCgpXG4gIHBhcmFsbGF4U21vb3RobmVzczogbnVtYmVyO1xuXG4gIEBJbnB1dCgpXG4gIHBhcmFsbGF4RGlyZWN0aW9uPzogUGFyYWxsYXhEaXJlY3Rpb247XG5cbiAgQElucHV0KClcbiAgcGFyYWxsYXhUaW1pbmdGdW5jdGlvbj86IHN0cmluZztcblxuICBASW5wdXQoKVxuICBwYXJhbGxheFRocm90dGxlVGltZT86IG51bWJlcjtcblxuICAvLyBTZXR0aW5nIHRoZSB2YWx1ZXMgYWZ0ZXIgdmFsaWRhdGlvblxuICBwcml2YXRlIF9wYXJhbGxheFNwZWVkVmFsOiBudW1iZXI7XG4gIHByaXZhdGUgX3BhcmFsbGF4U21vb3RobmVzc1ZhbDogbnVtYmVyO1xuICBwcml2YXRlIF9wYXJhbGxheFRpbWluZ0Z1blZhbDogc3RyaW5nID0gJ2xpbmVhcic7XG4gIHByaXZhdGUgX3BhcmFsbGF4VGhyb3R0bGVUaW1lOiBudW1iZXIgPSAwO1xuXG4gIHNjcm9sbFN1YnNjcmlidGlvbjogU3Vic2NyaXB0aW9uO1xuICBpc1ByeEVsSW5WaWV3cG9ydDogYm9vbGVhbjtcbiAgZGlyZWN0aXZlTmFtZTogc3RyaW5nID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBlbGVtOiBFbGVtZW50UmVmLFxuICAgIHB1YmxpYyByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgcGxhdGZvcm1JZDogT2JqZWN0XG4gICkge31cblxuICBuZ09uSW5pdCgpIHtcbiAgICBpZiAoaXNQbGF0Zm9ybVNlcnZlcih0aGlzLnBsYXRmb3JtSWQpKSByZXR1cm47XG5cbiAgICAvLyBJbml0aW5nIHBhcmFsbGF4IGVmZmVjdCBhbmQgc2V0dGluZyBlbGVtZW50IHN0eWxlc1xuICAgIHRoaXMuaW5pdFBhcmFsbGF4KCk7XG4gICAgdGhpcy5zZXRQYXJhbGxheEVsVHJhbnNmb3JtKCk7XG4gICAgdGhpcy5zZXRQYXJhbGxheFRyYW5zaXRpb24oKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICAvLyBTZXR0aW5nIHBhcmFsbGF4IG9wdGlvbnMgZnJvbSBjb25maWcgb2JqZWN0IG9yIGlucHV0IHByb3BzXG4gICAgY29uc3QgcHJseFNwZWVkID1cbiAgICAgIChjaGFuZ2VzWydwYXJhbGxheFNwZWVkJ10gJiYgY2hhbmdlc1sncGFyYWxsYXhTcGVlZCddLmN1cnJlbnRWYWx1ZSkgfHxcbiAgICAgIChjaGFuZ2VzWydjb25maWcnXSAmJiBjaGFuZ2VzWydjb25maWcnXS5jdXJyZW50VmFsdWUucGFyYWxsYXhTcGVlZCk7XG5cbiAgICBjb25zdCBwcmx4U21vb3RobmVzcyA9XG4gICAgICAoY2hhbmdlc1sncGFyYWxsYXhTbW9vdGhuZXNzJ10gJiYgY2hhbmdlc1sncGFyYWxsYXhTbW9vdGhuZXNzJ10uY3VycmVudFZhbHVlKSB8fFxuICAgICAgKGNoYW5nZXNbJ2NvbmZpZyddICYmIGNoYW5nZXNbJ2NvbmZpZyddLmN1cnJlbnRWYWx1ZS5wYXJhbGxheFNtb290aG5lc3MpO1xuXG4gICAgY29uc3QgcHJseERpcmVjdGlvbiA9XG4gICAgICAoY2hhbmdlc1sncGFyYWxsYXhEaXJlY3Rpb24nXSAmJiBjaGFuZ2VzWydwYXJhbGxheERpcmVjdGlvbiddLmN1cnJlbnRWYWx1ZSkgfHxcbiAgICAgIChjaGFuZ2VzWydjb25maWcnXSAmJiBjaGFuZ2VzWydjb25maWcnXS5jdXJyZW50VmFsdWUucGFyYWxsYXhEaXJlY3Rpb24pO1xuXG4gICAgY29uc3QgcHJseFRpbWluZ0Z1bmN0aW9uID1cbiAgICAgIChjaGFuZ2VzWydwYXJhbGxheFRpbWluZ0Z1bmN0aW9uJ10gJiYgY2hhbmdlc1sncGFyYWxsYXhUaW1pbmdGdW5jdGlvbiddLmN1cnJlbnRWYWx1ZSkgfHxcbiAgICAgIChjaGFuZ2VzWydjb25maWcnXSAmJiBjaGFuZ2VzWydjb25maWcnXS5jdXJyZW50VmFsdWUucGFyYWxsYXhUaW1pbmdGdW5jdGlvbik7XG5cbiAgICBjb25zdCBwcmx4VGhyb3R0bGVUaW1lID1cbiAgICAgIChjaGFuZ2VzWydwYXJhbGxheFRocm90dGxlVGltZSddICYmIGNoYW5nZXNbJ3BhcmFsbGF4VGhyb3R0bGVUaW1lJ10uY3VycmVudFZhbHVlKSB8fFxuICAgICAgKGNoYW5nZXNbJ2NvbmZpZyddICYmIGNoYW5nZXNbJ2NvbmZpZyddLmN1cnJlbnRWYWx1ZS5wYXJhbGxheFRocm90dGxlVGltZSk7XG5cbiAgICB0aGlzLnNldFBhcmFsbGF4U3BlZWQocHJseFNwZWVkKTtcbiAgICB0aGlzLnNldFBhcmFsbGF4U21vb3RobmVzcyhwcmx4U21vb3RobmVzcyk7XG4gICAgdGhpcy5zZXRQYXJhbGxheERpcmVjdGlvbihwcmx4RGlyZWN0aW9uKTtcbiAgICB0aGlzLnNldFBhcmFsbGF4VGltaW5nRnVuKHBybHhUaW1pbmdGdW5jdGlvbik7XG4gICAgdGhpcy5zZXRQYXJhbGxheFRocm90dGxlVGltZShwcmx4VGhyb3R0bGVUaW1lKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHt9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zY3JvbGxTdWJzY3JpYnRpb24gJiYgdGhpcy5zY3JvbGxTdWJzY3JpYnRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIC8vIFNldHRpbmcgcGFyYWxsYXggZWZmZWN0IGFuZCBzZXR0aW5nIGVsZW1lbnQgc3R5bGVzXG4gIGluaXRQYXJhbGxheCgpOiB2b2lkIHtcbiAgICB0aGlzLnNjcm9sbFN1YnNjcmlidGlvbiA9IGZyb21FdmVudCh3aW5kb3csICdzY3JvbGwnKVxuICAgICAgLnBpcGUodGhyb3R0bGVUaW1lKHRoaXMucHJseFRocm90dGxlVGltZSkpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5zZXRQYXJhbGxheEVsVHJhbnNmb3JtKCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFNldHRpbmcgcGFyYWxsYXggc3BlZWQgZWZmZWN0IHN0eWxlc1xuICBzZXRQYXJhbGxheEVsVHJhbnNmb3JtKCk6IHZvaWQge1xuICAgIGxldCBzY3JvbGxlZCA9IHdpbmRvdy5wYWdlWU9mZnNldDtcbiAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgdGhpcy5lbGVtLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAndHJhbnNmb3JtJyxcbiAgICAgIGB0cmFuc2xhdGVZKCR7c2Nyb2xsZWQgKiB0aGlzLnBybHhTcGVlZH1weCkgdHJhbnNsYXRlWigwKWBcbiAgICApO1xuICB9XG5cbiAgLy8gU2V0dGluZyBwYXJhbGxheCBzbW9vdGggZWZmZWN0IHN0eWxlcywgYmFzZWQgb24gQ1NTIGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb25cbiAgc2V0UGFyYWxsYXhUcmFuc2l0aW9uKCkge1xuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICB0aGlzLmVsZW0ubmF0aXZlRWxlbWVudCxcbiAgICAgICd0cmFuc2l0aW9uJyxcbiAgICAgIGB0cmFuc2Zvcm0gJHt0aGlzLnBybHhTbW9vdGhuZXNzfXMgJHt0aGlzLnBybHhUaW1pbmdGdW59YFxuICAgICk7XG4gIH1cblxuICAvLyBTZXR0aW5nIHBhcmFsbGF4IHByb3BlcnRpZXNcbiAgc2V0UGFyYWxsYXhTcGVlZChzcGVlZFZhbDogYW55KTogdm9pZCB7XG4gICAgY29uc3QgcHJvcE5hbWUgPSAncGFyYWxsYXhTcGVlZCc7XG4gICAgdGhpcy52YWxpZGF0ZVBhcmFsbGF4U3BlZWQoc3BlZWRWYWwsIHByb3BOYW1lLCAnbnVtYmVyJykgJiYgKHRoaXMuX3BhcmFsbGF4U3BlZWRWYWwgPSBzcGVlZFZhbCk7XG4gIH1cblxuICBzZXRQYXJhbGxheFNtb290aG5lc3Moc21vb3RobmVzc1ZhbDogYW55KTogdm9pZCB7XG4gICAgY29uc3QgcHJvcE5hbWUgPSAncGFyYWxsYXhTbW9vdGhuZXNzJztcbiAgICB0aGlzLnZhbGlkYXRlUGFyYWxsYXhTbW9vdGhuZXNzKHNtb290aG5lc3NWYWwsIHByb3BOYW1lLCAnbnVtYmVyJykgJiZcbiAgICAgICh0aGlzLl9wYXJhbGxheFNtb290aG5lc3NWYWwgPSBzbW9vdGhuZXNzVmFsKTtcbiAgfVxuXG4gIHNldFBhcmFsbGF4RGlyZWN0aW9uKGRpcmVjdGlvblZhbDogYW55KTogdm9pZCB7XG4gICAgY29uc3QgcHJvcE5hbWUgPSAncGFyYWxsYXhEaXJlY3Rpb24nO1xuICAgIGRpcmVjdGlvblZhbCAmJlxuICAgICAgdGhpcy5pc1R5cGVPZihkaXJlY3Rpb25WYWwsICdzdHJpbmcnLCBwcm9wTmFtZSkgJiZcbiAgICAgIGRpcmVjdGlvblZhbCA9PT0gJ3JldmVyc2UnICYmXG4gICAgICAodGhpcy5fcGFyYWxsYXhTcGVlZFZhbCAqPSAtMSk7XG4gIH1cblxuICBzZXRQYXJhbGxheFRpbWluZ0Z1bih0aW1pbmdGdW46IGFueSk6IHZvaWQge1xuICAgIGNvbnN0IHByb3BOYW1lID0gJ3BhcmFsbGF4VGltaW5nRnVuY3Rpb24nO1xuICAgIHRpbWluZ0Z1biAmJlxuICAgICAgdGhpcy5pc1R5cGVPZih0aW1pbmdGdW4sICdzdHJpbmcnLCBwcm9wTmFtZSkgJiZcbiAgICAgICh0aGlzLl9wYXJhbGxheFRpbWluZ0Z1blZhbCA9IHRpbWluZ0Z1bik7XG4gIH1cblxuICBzZXRQYXJhbGxheFRocm90dGxlVGltZSh0aHJvdHRsZVRpbWU6IGFueSk6IHZvaWQge1xuICAgIGNvbnN0IHByb3BOYW1lID0gJ3BhcmFsbGF4VGhyb3R0bGVUaW1lJztcbiAgICB0aHJvdHRsZVRpbWUgJiZcbiAgICAgIHRoaXMuaXNUeXBlT2YodGhyb3R0bGVUaW1lLCAnbnVtYmVyJywgcHJvcE5hbWUpICYmXG4gICAgICAodGhpcy5fcGFyYWxsYXhUaHJvdHRsZVRpbWUgPSB0aHJvdHRsZVRpbWUpO1xuICB9XG5cbiAgLy8gR2V0dGVycyBmb3IgcGFyYWxsYXggb3B0aW9uc1xuICBnZXQgcHJseFNwZWVkKCkge1xuICAgIHJldHVybiB0aGlzLl9wYXJhbGxheFNwZWVkVmFsO1xuICB9XG5cbiAgZ2V0IHBybHhTbW9vdGhuZXNzKCkge1xuICAgIHJldHVybiB0aGlzLl9wYXJhbGxheFNtb290aG5lc3NWYWw7XG4gIH1cblxuICBnZXQgcHJseFRpbWluZ0Z1bigpIHtcbiAgICByZXR1cm4gdGhpcy5fcGFyYWxsYXhUaW1pbmdGdW5WYWw7XG4gIH1cblxuICBnZXQgcHJseFRocm90dGxlVGltZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fcGFyYWxsYXhUaHJvdHRsZVRpbWU7XG4gIH1cblxuICAvLyBWYWxpZGF0aW9uIGZ1bmN0aW9uc1xuICBpc1Byb3ZpZGVkKHZhbHVlOiBhbnksIHByb3BOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBpc05vdFByb3ZpZGVkID0gdmFsdWUgPT0gbnVsbCB8fCB2YWx1ZSA9PT0gJyc7XG4gICAgaWYgKGlzTm90UHJvdmlkZWQgJiYgaXNEZXZNb2RlKCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7dGhpcy5kaXJlY3RpdmVOYW1lfTogQElucHV0IFske3Byb3BOYW1lfV0gaXMgcmVxdWlyZWQsIGJ1dCB3YXMgbm90IHByb3ZpZGVkYFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBpc1R5cGVPZih2YWx1ZTogYW55LCByZXF1aXJlZFR5cGU6ICdzdHJpbmcnIHwgJ251bWJlcicgfCAnYm9vbGVhbicsIHByb3BOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBpc1JlcXVpcmVkVHlwZSA9IHR5cGVvZiB2YWx1ZSA9PT0gcmVxdWlyZWRUeXBlO1xuICAgIGlmICghaXNSZXF1aXJlZFR5cGUgJiYgaXNEZXZNb2RlKCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7XG4gICAgICAgICAgdGhpcy5kaXJlY3RpdmVOYW1lXG4gICAgICAgIH06IEBJbnB1dCBbJHtwcm9wTmFtZX1dIGlzIGV4cGVjdGVkIHRvIGJlIG9mIHR5cGUgJyR7cmVxdWlyZWRUeXBlfScsIGJ1dCB0eXBlICcke3R5cGVvZiB2YWx1ZX0nIHdhcyBwcm92aWRlZGBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgaXNQb3NpdGl2ZSh2YWx1ZTogbnVtYmVyLCBwcm9wTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgaXNSZXF1aXJlZFR5cGUgPSB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xuICAgIGNvbnN0IGlzVmFsaWQgPSB2YWx1ZSA+PSAwO1xuXG4gICAgaWYgKGlzUmVxdWlyZWRUeXBlICYmICFpc1ZhbGlkICYmIGlzRGV2TW9kZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke1xuICAgICAgICAgIHRoaXMuZGlyZWN0aXZlTmFtZVxuICAgICAgICB9OiBASW5wdXQgWyR7cHJvcE5hbWV9XSBpcyBleHBlY3RlZCB0byBiZSBwb3NpdGl2ZSB2YWx1ZSwgYnV0IG5lZ2F0aXZlICcke3ZhbHVlfScgdmFsdWUgd2FzIHByb3ZpZGVkYFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvLyBFeGVjdXRpbmcgdmFsaWRhdGlvbiBmdW5jdGlvbnMgdG8gdmFsaWRhdGUgcGFyYWxsYXggc3BlZWRcbiAgdmFsaWRhdGVQYXJhbGxheFNwZWVkKFxuICAgIHZhbHVlOiBhbnksXG4gICAgcHJvcE5hbWU6IHN0cmluZyxcbiAgICByZXF1aXJlZFR5cGU6ICdzdHJpbmcnIHwgJ251bWJlcicgfCAnYm9vbGVhbidcbiAgKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuaXNQcm92aWRlZCh2YWx1ZSwgcHJvcE5hbWUpICYmXG4gICAgICB0aGlzLmlzVHlwZU9mKHZhbHVlLCByZXF1aXJlZFR5cGUsIHByb3BOYW1lKSAmJlxuICAgICAgdGhpcy5pc1Bvc2l0aXZlKHZhbHVlLCBwcm9wTmFtZSlcbiAgICApO1xuICB9XG5cbiAgLy8gRXhlY3V0aW5nIHZhbGlkYXRpb24gZnVuY3Rpb25zIHRvIHZhbGlkYXRlIHBhcmFsbGF4IHNtb290aG5lc3NcbiAgdmFsaWRhdGVQYXJhbGxheFNtb290aG5lc3MoXG4gICAgdmFsdWU6IGFueSxcbiAgICBwcm9wTmFtZTogc3RyaW5nLFxuICAgIHJlcXVpcmVkVHlwZTogJ3N0cmluZycgfCAnbnVtYmVyJyB8ICdib29sZWFuJ1xuICApIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5pc1Byb3ZpZGVkKHZhbHVlLCBwcm9wTmFtZSkgJiZcbiAgICAgIHRoaXMuaXNUeXBlT2YodmFsdWUsIHJlcXVpcmVkVHlwZSwgcHJvcE5hbWUpICYmXG4gICAgICB0aGlzLmlzUG9zaXRpdmUodmFsdWUsIHByb3BOYW1lKVxuICAgICk7XG4gIH1cbn1cbiJdfQ==