carousel-angular
Version:
A simple carousel component for Angular 14+ based on 'angular-responsive-carousel' by Ivy Laboratory http://ivylab.space
347 lines • 42 kB
JavaScript
export class Touches {
constructor(properties) {
this.eventType = undefined;
this.handlers = {};
this.startX = 0;
this.startY = 0;
this.lastTap = 0;
this.doubleTapMinTimeout = 300;
this.tapMinTimeout = 200;
this.touchstartTime = 0;
this.i = 0;
this.isMousedown = false;
this._touchListeners = {
touchstart: 'handleTouchstart',
touchmove: 'handleTouchmove',
touchend: 'handleTouchend'
};
this._mouseListeners = {
mousedown: 'handleMousedown',
mousemove: 'handleMousemove',
mouseup: 'handleMouseup',
wheel: 'handleWheel'
};
this._otherListeners = {
resize: 'handleResize'
};
/*
* Listeners
*/
/* Touchstart */
this.handleTouchstart = (event) => {
this.elementPosition = this.getElementPosition();
this.touchstartTime = new Date().getTime();
if (this.eventType === undefined) {
this.getTouchstartPosition(event);
}
this.runHandler('touchstart', event);
};
/* Touchmove */
this.handleTouchmove = (event) => {
const { touches } = event;
// Pan
if (this.detectPan(touches)) {
this.runHandler('pan', event);
}
// Pinch
if (this.detectPinch(event)) {
this.runHandler('pinch', event);
}
// Linear swipe
switch (this.detectLinearSwipe(event)) {
case 'horizontal-swipe':
event.swipeType = 'horizontal-swipe';
this.runHandler('horizontal-swipe', event);
break;
case 'vertical-swipe':
event.swipeType = 'vertical-swipe';
this.runHandler('vertical-swipe', event);
break;
}
// Linear swipe
if (this.detectLinearSwipe(event) ||
this.eventType === 'horizontal-swipe' ||
this.eventType === 'vertical-swipe') {
this.handleLinearSwipe(event);
}
};
/* Touchend */
this.handleTouchend = (event) => {
const { touches } = event;
// Double Tap
if (this.detectDoubleTap()) {
this.runHandler('double-tap', event);
}
// Tap
this.detectTap();
this.runHandler('touchend', event);
this.eventType = 'touchend';
if (touches && touches.length === 0) {
this.eventType = undefined;
this.i = 0;
}
};
/* Mousedown */
this.handleMousedown = (event) => {
this.isMousedown = true;
this.elementPosition = this.getElementPosition();
this.touchstartTime = new Date().getTime();
if (this.eventType === undefined) {
this.getMousedownPosition(event);
}
this.runHandler('mousedown', event);
};
/* Mousemove */
this.handleMousemove = (event) => {
// event.preventDefault();
if (!this.isMousedown) {
return;
}
// Pan
this.runHandler('pan', event);
// Linear swipe
switch (this.detectLinearSwipe(event)) {
case 'horizontal-swipe':
event.swipeType = 'horizontal-swipe';
this.runHandler('horizontal-swipe', event);
break;
case 'vertical-swipe':
event.swipeType = 'vertical-swipe';
this.runHandler('vertical-swipe', event);
break;
}
// Linear swipe
if (this.detectLinearSwipe(event) ||
this.eventType === 'horizontal-swipe' ||
this.eventType === 'vertical-swipe') {
this.handleLinearSwipe(event);
}
};
/* Mouseup */
this.handleMouseup = (event) => {
// Tap
this.detectTap();
this.isMousedown = false;
this.runHandler('mouseup', event);
this.eventType = undefined;
this.i = 0;
};
/* Wheel */
this.handleWheel = (event) => {
this.runHandler('wheel', event);
};
/* Resize */
this.handleResize = (event) => {
this.runHandler('resize', event);
};
this.properties = properties;
this.element = this.properties.element;
this.elementPosition = this.getElementPosition();
this.toggleEventListeners('addEventListener');
}
get touchListeners() {
return this.properties.touchListeners
? this.properties.touchListeners
: this._touchListeners;
}
get mouseListeners() {
return this.properties.mouseListeners
? this.properties.mouseListeners
: this._mouseListeners;
}
get otherListeners() {
return this.properties.otherListeners
? this.properties.otherListeners
: this._otherListeners;
}
destroy() {
this.toggleEventListeners('removeEventListener');
}
toggleEventListeners(action) {
let listeners;
if (this.properties.listeners === 'mouse and touch') {
listeners = Object.assign(this.touchListeners, this.mouseListeners);
}
else {
listeners = this.detectTouchScreen()
? this.touchListeners
: this.mouseListeners;
}
if (this.properties.resize) {
listeners = Object.assign(listeners, this.otherListeners);
}
for (const listener in listeners) {
const handler = listeners[listener];
// Window
if (listener === 'resize') {
if (action === 'addEventListener') {
window.addEventListener(listener, this[handler], false);
}
if (action === 'removeEventListener') {
window.removeEventListener(listener, this[handler], false);
}
// Document
}
else if (listener === 'mouseup' || listener === 'mousemove') {
if (action === 'addEventListener') {
document.addEventListener(listener, this[handler], {
passive: false
});
}
if (action === 'removeEventListener') {
document.removeEventListener(listener, this[handler], false);
}
// Element
}
else {
if (action === 'addEventListener') {
this.element.addEventListener(listener, this[handler], false);
}
if (action === 'removeEventListener') {
this.element.removeEventListener(listener, this[handler], false);
}
}
}
}
addEventListeners(listener) {
const handler = this._mouseListeners[listener];
window.addEventListener(listener, this[handler], false);
}
removeEventListeners(listener) {
const handler = this._mouseListeners[listener];
window.removeEventListener(listener, this[handler], false);
}
handleLinearSwipe(event) {
// event.preventDefault();
this.i++;
if (this.i > 3) {
this.eventType = this.getLinearSwipeType(event);
}
if (this.eventType === 'horizontal-swipe') {
this.runHandler('horizontal-swipe', event);
}
if (this.eventType === 'vertical-swipe') {
this.runHandler('vertical-swipe', event);
}
}
runHandler(eventName, response) {
if (this.handlers[eventName]) {
this.handlers[eventName](response);
}
}
/*
* Detection
*/
detectPan(touches) {
return ((touches.length === 1 && !this.eventType) || this.eventType === 'pan');
}
detectDoubleTap() {
if (this.eventType != undefined) {
return;
}
const currentTime = new Date().getTime();
const tapLength = currentTime - this.lastTap;
clearTimeout(this.doubleTapTimeout);
if (tapLength < this.doubleTapMinTimeout && tapLength > 0) {
return true;
}
this.doubleTapTimeout = setTimeout(() => {
clearTimeout(this.doubleTapTimeout);
}, this.doubleTapMinTimeout);
this.lastTap = currentTime;
return undefined;
}
detectTap() {
if (this.eventType != undefined) {
return;
}
const currentTime = new Date().getTime();
const tapLength = currentTime - this.touchstartTime;
if (tapLength > 0) {
if (tapLength < this.tapMinTimeout) {
this.runHandler('tap', event);
}
else {
this.runHandler('longtap', event);
}
}
}
detectPinch(event) {
const { touches } = event;
return ((touches.length === 2 && this.eventType === undefined) ||
this.eventType === 'pinch');
}
detectLinearSwipe(event) {
const { touches } = event;
if (touches) {
if ((touches.length === 1 && !this.eventType) ||
this.eventType === 'horizontal-swipe' ||
this.eventType === 'vertical-swipe') {
return this.getLinearSwipeType(event);
}
}
else if (!this.eventType ||
this.eventType === 'horizontal-swipe' ||
this.eventType === 'vertical-swipe') {
return this.getLinearSwipeType(event);
}
return undefined;
}
getLinearSwipeType(event) {
if (this.eventType !== 'horizontal-swipe' &&
this.eventType !== 'vertical-swipe') {
const movementX = Math.abs(this.moveLeft(0, event) - this.startX);
const movementY = Math.abs(this.moveTop(0, event) - this.startY);
if (movementY * 3 > movementX) {
return 'vertical-swipe';
}
return 'horizontal-swipe';
}
return this.eventType;
}
getElementPosition() {
return this.element.getBoundingClientRect();
}
getTouchstartPosition(event) {
this.startX = event.touches[0].clientX - this.elementPosition.left;
this.startY = event.touches[0].clientY - this.elementPosition.top;
}
getMousedownPosition(event) {
this.startX = event.clientX - this.elementPosition.left;
this.startY = event.clientY - this.elementPosition.top;
}
moveLeft(index, event) {
const { touches } = event;
if (touches) {
return touches[index].clientX - this.elementPosition.left;
}
return event.clientX - this.elementPosition.left;
}
moveTop(index, event) {
const { touches } = event;
if (touches) {
return touches[index].clientY - this.elementPosition.top;
}
return event.clientY - this.elementPosition.top;
}
detectTouchScreen() {
const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
const mq = function (query) {
return window.matchMedia(query).matches;
};
if ('ontouchstart' in window) {
return true;
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// https://git.io/vznFH
const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
return mq(query);
}
/* Public properties and methods */
on(event, handler) {
if (event) {
this.handlers[event] = handler;
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG91Y2hlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2Nhcm91c2VsLWFuZ3VsYXIvc3JjL2xpYi90b3VjaGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQTJCQSxNQUFNLE9BQU8sT0FBTztJQWdFbEIsWUFBWSxVQUFzQjtRQXpEbEMsY0FBUyxHQUFjLFNBQVMsQ0FBQztRQUVqQyxhQUFRLEdBQVEsRUFBRSxDQUFDO1FBRW5CLFdBQU0sR0FBRyxDQUFDLENBQUM7UUFFWCxXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBRVgsWUFBTyxHQUFHLENBQUMsQ0FBQztRQUlaLHdCQUFtQixHQUFHLEdBQUcsQ0FBQztRQUUxQixrQkFBYSxHQUFHLEdBQUcsQ0FBQztRQUVwQixtQkFBYyxHQUFHLENBQUMsQ0FBQztRQUVuQixNQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRU4sZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFFcEIsb0JBQWUsR0FBUTtZQUNyQixVQUFVLEVBQUUsa0JBQWtCO1lBQzlCLFNBQVMsRUFBRSxpQkFBaUI7WUFDNUIsUUFBUSxFQUFFLGdCQUFnQjtTQUMzQixDQUFDO1FBRUYsb0JBQWUsR0FBUTtZQUNyQixTQUFTLEVBQUUsaUJBQWlCO1lBQzVCLFNBQVMsRUFBRSxpQkFBaUI7WUFDNUIsT0FBTyxFQUFFLGVBQWU7WUFDeEIsS0FBSyxFQUFFLGFBQWE7U0FDckIsQ0FBQztRQUVGLG9CQUFlLEdBQVE7WUFDckIsTUFBTSxFQUFFLGNBQWM7U0FDdkIsQ0FBQztRQTBGRjs7V0FFRztRQUVILGdCQUFnQjtRQUVoQixxQkFBZ0IsR0FBRyxDQUFDLEtBQVUsRUFBRSxFQUFFO1lBQ2hDLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDakQsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBRTNDLElBQUksSUFBSSxDQUFDLFNB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Q0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDO0lBQ2xELENBQUM7SUFFRCxpQkFBaUI7UUFDZixNQUFNLFFBQVEsR0FBRywyQkFBMkIsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEQsTUFBTSxFQUFFLEdBQUcsVUFBVSxLQUFVO1lBQzdCLE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDMUMsQ0FBQyxDQUFDO1FBRUYsSUFBSSxjQUFjLElBQUksTUFBTSxFQUFFO1lBQzVCLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFFRCxxRkFBcUY7UUFDckYsdUJBQXVCO1FBQ3ZCLE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUN4RSxFQUFFLENBQ0gsQ0FBQztRQUNGLE9BQU8sRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25CLENBQUM7SUFFRCxtQ0FBbUM7SUFDbkMsRUFBRSxDQUFDLEtBQWdCLEVBQUUsT0FBaUI7UUFDcEMsSUFBSSxLQUFLLEVBQUU7WUFDVCxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQztTQUNoQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgUHJvcGVydGllcyB7XG4gIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICBsaXN0ZW5lcnM/OiAnYXV0bycgfCAnbW91c2UgYW5kIHRvdWNoJztcbiAgdG91Y2hMaXN0ZW5lcnM/OiBhbnk7XG4gIG1vdXNlTGlzdGVuZXJzPzogYW55O1xuICBvdGhlckxpc3RlbmVycz86IGFueTtcbiAgcmVzaXplPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IHR5cGUgRXZlbnRUeXBlID1cbiAgfCB1bmRlZmluZWRcbiAgfCAndG91Y2hlbmQnXG4gIHwgJ3BhbidcbiAgfCAncGluY2gnXG4gIHwgJ2hvcml6b250YWwtc3dpcGUnXG4gIHwgJ3ZlcnRpY2FsLXN3aXBlJ1xuICB8ICd0YXAnXG4gIHwgJ2xvbmd0YXAnO1xuZXhwb3J0IHR5cGUgVG91Y2hIYW5kbGVyID1cbiAgfCAnaGFuZGxlVG91Y2hzdGFydCdcbiAgfCAnaGFuZGxlVG91Y2htb3ZlJ1xuICB8ICdoYW5kbGVUb3VjaGVuZCc7XG5leHBvcnQgdHlwZSBNb3VzZUhhbmRsZXIgPVxuICB8ICdoYW5kbGVNb3VzZWRvd24nXG4gIHwgJ2hhbmRsZU1vdXNlbW92ZSdcbiAgfCAnaGFuZGxlTW91c2V1cCc7XG5cbmV4cG9ydCBjbGFzcyBUb3VjaGVzIHtcbiAgcHJvcGVydGllczogUHJvcGVydGllcztcblxuICBlbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICBlbGVtZW50UG9zaXRpb246IENsaWVudFJlY3Q7XG5cbiAgZXZlbnRUeXBlOiBFdmVudFR5cGUgPSB1bmRlZmluZWQ7XG5cbiAgaGFuZGxlcnM6IGFueSA9IHt9O1xuXG4gIHN0YXJ0WCA9IDA7XG5cbiAgc3RhcnRZID0gMDtcblxuICBsYXN0VGFwID0gMDtcblxuICBkb3VibGVUYXBUaW1lb3V0OiBhbnk7XG5cbiAgZG91YmxlVGFwTWluVGltZW91dCA9IDMwMDtcblxuICB0YXBNaW5UaW1lb3V0ID0gMjAwO1xuXG4gIHRvdWNoc3RhcnRUaW1lID0gMDtcblxuICBpID0gMDtcblxuICBpc01vdXNlZG93biA9IGZhbHNlO1xuXG4gIF90b3VjaExpc3RlbmVyczogYW55ID0ge1xuICAgIHRvdWNoc3RhcnQ6ICdoYW5kbGVUb3VjaHN0YXJ0JyxcbiAgICB0b3VjaG1vdmU6ICdoYW5kbGVUb3VjaG1vdmUnLFxuICAgIHRvdWNoZW5kOiAnaGFuZGxlVG91Y2hlbmQnXG4gIH07XG5cbiAgX21vdXNlTGlzdGVuZXJzOiBhbnkgPSB7XG4gICAgbW91c2Vkb3duOiAnaGFuZGxlTW91c2Vkb3duJyxcbiAgICBtb3VzZW1vdmU6ICdoYW5kbGVNb3VzZW1vdmUnLFxuICAgIG1vdXNldXA6ICdoYW5kbGVNb3VzZXVwJyxcbiAgICB3aGVlbDogJ2hhbmRsZVdoZWVsJ1xuICB9O1xuXG4gIF9vdGhlckxpc3RlbmVyczogYW55ID0ge1xuICAgIHJlc2l6ZTogJ2hhbmRsZVJlc2l6ZSdcbiAgfTtcblxuICBnZXQgdG91Y2hMaXN0ZW5lcnMoKSB7XG4gICAgcmV0dXJuIHRoaXMucHJvcGVydGllcy50b3VjaExpc3RlbmVyc1xuICAgICAgPyB0aGlzLnByb3BlcnRpZXMudG91Y2hMaXN0ZW5lcnNcbiAgICAgIDogdGhpcy5fdG91Y2hMaXN0ZW5lcnM7XG4gIH1cblxuICBnZXQgbW91c2VMaXN0ZW5lcnMoKSB7XG4gICAgcmV0dXJuIHRoaXMucHJvcGVydGllcy5tb3VzZUxpc3RlbmVyc1xuICAgICAgPyB0aGlzLnByb3BlcnRpZXMubW91c2VMaXN0ZW5lcnNcbiAgICAgIDogdGhpcy5fbW91c2VMaXN0ZW5lcnM7XG4gIH1cblxuICBnZXQgb3RoZXJMaXN0ZW5lcnMoKSB7XG4gICAgcmV0dXJuIHRoaXMucHJvcGVydGllcy5vdGhlckxpc3RlbmVyc1xuICAgICAgPyB0aGlzLnByb3BlcnRpZXMub3RoZXJMaXN0ZW5lcnNcbiAgICAgIDogdGhpcy5fb3RoZXJMaXN0ZW5lcnM7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcm9wZXJ0aWVzOiBQcm9wZXJ0aWVzKSB7XG4gICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcbiAgICB0aGlzLmVsZW1lbnQgPSB0aGlzLnByb3BlcnRpZXMuZWxlbWVudDtcbiAgICB0aGlzLmVsZW1lbnRQb3NpdGlvbiA9IHRoaXMuZ2V0RWxlbWVudFBvc2l0aW9uKCk7XG5cbiAgICB0aGlzLnRvZ2dsZUV2ZW50TGlzdGVuZXJzKCdhZGRFdmVudExpc3RlbmVyJyk7XG4gIH1cblxuICBkZXN0cm95KCkge1xuICAgIHRoaXMudG9nZ2xlRXZlbnRMaXN0ZW5lcnMoJ3JlbW92ZUV2ZW50TGlzdGVuZXInKTtcbiAgfVxuXG4gIHRvZ2dsZUV2ZW50TGlzdGVuZXJzKGFjdGlvbjogJ2FkZEV2ZW50TGlzdGVuZXInIHwgJ3JlbW92ZUV2ZW50TGlzdGVuZXInKSB7XG4gICAgbGV0IGxpc3RlbmVycztcblxuICAgIGlmICh0aGlzLnByb3BlcnRpZXMubGlzdGVuZXJzID09PSAnbW91c2UgYW5kIHRvdWNoJykge1xuICAgICAgbGlzdGVuZXJzID0gT2JqZWN0LmFzc2lnbih0aGlzLnRvdWNoTGlzdGVuZXJzLCB0aGlzLm1vdXNlTGlzdGVuZXJzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGlzdGVuZXJzID0gdGhpcy5kZXRlY3RUb3VjaFNjcmVlbigpXG4gICAgICAgID8gdGhpcy50b3VjaExpc3RlbmVyc1xuICAgICAgICA6IHRoaXMubW91c2VMaXN0ZW5lcnM7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucHJvcGVydGllcy5yZXNpemUpIHtcbiAgICAgIGxpc3RlbmVycyA9IE9iamVjdC5hc3NpZ24obGlzdGVuZXJzLCB0aGlzLm90aGVyTGlzdGVuZXJzKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIGluIGxpc3RlbmVycykge1xuICAgICAgY29uc3QgaGFuZGxlcjogTW91c2VIYW5kbGVyID0gbGlzdGVuZXJzW2xpc3RlbmVyXTtcblxuICAgICAgLy8gV2luZG93XG4gICAgICBpZiAobGlzdGVuZXIgPT09ICdyZXNpemUnKSB7XG4gICAgICAgIGlmIChhY3Rpb24gPT09ICdhZGRFdmVudExpc3RlbmVyJykge1xuICAgICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKGxpc3RlbmVyLCB0aGlzW2hhbmRsZXJdLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjdGlvbiA9PT0gJ3JlbW92ZUV2ZW50TGlzdGVuZXInKSB7XG4gICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIobGlzdGVuZXIsIHRoaXNbaGFuZGxlcl0sIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBEb2N1bWVudFxuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lciA9PT0gJ21vdXNldXAnIHx8IGxpc3RlbmVyID09PSAnbW91c2Vtb3ZlJykge1xuICAgICAgICBpZiAoYWN0aW9uID09PSAnYWRkRXZlbnRMaXN0ZW5lcicpIHtcbiAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGxpc3RlbmVyLCB0aGlzW2hhbmRsZXJdLCB7XG4gICAgICAgICAgICBwYXNzaXZlOiBmYWxzZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhY3Rpb24gPT09ICdyZW1vdmVFdmVudExpc3RlbmVyJykge1xuICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIobGlzdGVuZXIsIHRoaXNbaGFuZGxlcl0sIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBFbGVtZW50XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoYWN0aW9uID09PSAnYWRkRXZlbnRMaXN0ZW5lcicpIHtcbiAgICAgICAgICB0aGlzLmVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhY3Rpb24gPT09ICdyZW1vdmVFdmVudExpc3RlbmVyJykge1xuICAgICAgICAgIHRoaXMuZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGxpc3RlbmVyLCB0aGlzW2hhbmRsZXJdLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhZGRFdmVudExpc3RlbmVycyhsaXN0ZW5lcjogc3RyaW5nKSB7XG4gICAgY29uc3QgaGFuZGxlcjogTW91c2VIYW5kbGVyID0gdGhpcy5fbW91c2VMaXN0ZW5lcnNbbGlzdGVuZXJdO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKGxpc3RlbmVyLCB0aGlzW2hhbmRsZXJdLCBmYWxzZSk7XG4gIH1cblxuICByZW1vdmVFdmVudExpc3RlbmVycyhsaXN0ZW5lcjogc3RyaW5nKSB7XG4gICAgY29uc3QgaGFuZGxlcjogTW91c2VIYW5kbGVyID0gdGhpcy5fbW91c2VMaXN0ZW5lcnNbbGlzdGVuZXJdO1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKGxpc3RlbmVyLCB0aGlzW2hhbmRsZXJdLCBmYWxzZSk7XG4gIH1cblxuICAvKlxuICAgKiBMaXN0ZW5lcnNcbiAgICovXG5cbiAgLyogVG91Y2hzdGFydCAqL1xuXG4gIGhhbmRsZVRvdWNoc3RhcnQgPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgIHRoaXMuZWxlbWVudFBvc2l0aW9uID0gdGhpcy5nZXRFbGVtZW50UG9zaXRpb24oKTtcbiAgICB0aGlzLnRvdWNoc3RhcnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICBpZiAodGhpcy5ldmVudFR5cGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5nZXRUb3VjaHN0YXJ0UG9zaXRpb24oZXZlbnQpO1xuICAgIH1cblxuICAgIHRoaXMucnVuSGFuZGxlcigndG91Y2hzdGFydCcsIGV2ZW50KTtcbiAgfTtcblxuICAvKiBUb3VjaG1vdmUgKi9cblxuICBoYW5kbGVUb3VjaG1vdmUgPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgIGNvbnN0IHsgdG91Y2hlcyB9ID0gZXZlbnQ7XG5cbiAgICAvLyBQYW5cbiAgICBpZiAodGhpcy5kZXRlY3RQYW4odG91Y2hlcykpIHtcbiAgICAgIHRoaXMucnVuSGFuZGxlcigncGFuJywgZXZlbnQpO1xuICAgIH1cblxuICAgIC8vIFBpbmNoXG4gICAgaWYgKHRoaXMuZGV0ZWN0UGluY2goZXZlbnQpKSB7XG4gICAgICB0aGlzLnJ1bkhhbmRsZXIoJ3BpbmNoJywgZXZlbnQpO1xuICAgIH1cblxuICAgIC8vIExpbmVhciBzd2lwZVxuICAgIHN3aXRjaCAodGhpcy5kZXRlY3RMaW5lYXJTd2lwZShldmVudCkpIHtcbiAgICAgIGNhc2UgJ2hvcml6b250YWwtc3dpcGUnOlxuICAgICAgICBldmVudC5zd2lwZVR5cGUgPSAnaG9yaXpvbnRhbC1zd2lwZSc7XG4gICAgICAgIHRoaXMucnVuSGFuZGxlcignaG9yaXpvbnRhbC1zd2lwZScsIGV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd2ZXJ0aWNhbC1zd2lwZSc6XG4gICAgICAgIGV2ZW50LnN3aXBlVHlwZSA9ICd2ZXJ0aWNhbC1zd2lwZSc7XG4gICAgICAgIHRoaXMucnVuSGFuZGxlcigndmVydGljYWwtc3dpcGUnLCBldmVudCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIC8vIExpbmVhciBzd2lwZVxuICAgIGlmIChcbiAgICAgIHRoaXMuZGV0ZWN0TGluZWFyU3dpcGUoZXZlbnQpIHx8XG4gICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ2hvcml6b250YWwtc3dpcGUnIHx8XG4gICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ3ZlcnRpY2FsLXN3aXBlJ1xuICAgICkge1xuICAgICAgdGhpcy5oYW5kbGVMaW5lYXJTd2lwZShldmVudCk7XG4gICAgfVxuICB9O1xuXG4gIGhhbmRsZUxpbmVhclN3aXBlKGV2ZW50OiBhbnkpIHtcbiAgICAvLyBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgdGhpcy5pKys7XG5cbiAgICBpZiAodGhpcy5pID4gMykge1xuICAgICAgdGhpcy5ldmVudFR5cGUgPSB0aGlzLmdldExpbmVhclN3aXBlVHlwZShldmVudCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZXZlbnRUeXBlID09PSAnaG9yaXpvbnRhbC1zd2lwZScpIHtcbiAgICAgIHRoaXMucnVuSGFuZGxlcignaG9yaXpvbnRhbC1zd2lwZScsIGV2ZW50KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5ldmVudFR5cGUgPT09ICd2ZXJ0aWNhbC1zd2lwZScpIHtcbiAgICAgIHRoaXMucnVuSGFuZGxlcigndmVydGljYWwtc3dpcGUnLCBldmVudCk7XG4gICAgfVxuICB9XG5cbiAgLyogVG91Y2hlbmQgKi9cblxuICBoYW5kbGVUb3VjaGVuZCA9IChldmVudDogYW55KSA9PiB7XG4gICAgY29uc3QgeyB0b3VjaGVzIH0gPSBldmVudDtcblxuICAgIC8vIERvdWJsZSBUYXBcbiAgICBpZiAodGhpcy5kZXRlY3REb3VibGVUYXAoKSkge1xuICAgICAgdGhpcy5ydW5IYW5kbGVyKCdkb3VibGUtdGFwJywgZXZlbnQpO1xuICAgIH1cblxuICAgIC8vIFRhcFxuICAgIHRoaXMuZGV0ZWN0VGFwKCk7XG5cbiAgICB0aGlzLnJ1bkhhbmRsZXIoJ3RvdWNoZW5kJywgZXZlbnQpO1xuICAgIHRoaXMuZXZlbnRUeXBlID0gJ3RvdWNoZW5kJztcblxuICAgIGlmICh0b3VjaGVzICYmIHRvdWNoZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLmV2ZW50VHlwZSA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuaSA9IDA7XG4gICAgfVxuICB9O1xuXG4gIC8qIE1vdXNlZG93biAqL1xuXG4gIGhhbmRsZU1vdXNlZG93biA9IChldmVudDogYW55KSA9PiB7XG4gICAgdGhpcy5pc01vdXNlZG93biA9IHRydWU7XG4gICAgdGhpcy5lbGVtZW50UG9zaXRpb24gPSB0aGlzLmdldEVsZW1lbnRQb3NpdGlvbigpO1xuICAgIHRoaXMudG91Y2hzdGFydFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgIGlmICh0aGlzLmV2ZW50VHlwZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmdldE1vdXNlZG93blBvc2l0aW9uKGV2ZW50KTtcbiAgICB9XG5cbiAgICB0aGlzLnJ1bkhhbmRsZXIoJ21vdXNlZG93bicsIGV2ZW50KTtcbiAgfTtcblxuICAvKiBNb3VzZW1vdmUgKi9cblxuICBoYW5kbGVNb3VzZW1vdmUgPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgIC8vIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBpZiAoIXRoaXMuaXNNb3VzZWRvd24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBQYW5cbiAgICB0aGlzLnJ1bkhhbmRsZXIoJ3BhbicsIGV2ZW50KTtcblxuICAgIC8vIExpbmVhciBzd2lwZVxuICAgIHN3aXRjaCAodGhpcy5kZXRlY3RMaW5lYXJTd2lwZShldmVudCkpIHtcbiAgICAgIGNhc2UgJ2hvcml6b250YWwtc3dpcGUnOlxuICAgICAgICBldmVudC5zd2lwZVR5cGUgPSAnaG9yaXpvbnRhbC1zd2lwZSc7XG4gICAgICAgIHRoaXMucnVuSGFuZGxlcignaG9yaXpvbnRhbC1zd2lwZScsIGV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd2ZXJ0aWNhbC1zd2lwZSc6XG4gICAgICAgIGV2ZW50LnN3aXBlVHlwZSA9ICd2ZXJ0aWNhbC1zd2lwZSc7XG4gICAgICAgIHRoaXMucnVuSGFuZGxlcigndmVydGljYWwtc3dpcGUnLCBldmVudCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIC8vIExpbmVhciBzd2lwZVxuICAgIGlmIChcbiAgICAgIHRoaXMuZGV0ZWN0TGluZWFyU3dpcGUoZXZlbnQpIHx8XG4gICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ2hvcml6b250YWwtc3dpcGUnIHx8XG4gICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ3ZlcnRpY2FsLXN3aXBlJ1xuICAgICkge1xuICAgICAgdGhpcy5oYW5kbGVMaW5lYXJTd2lwZShldmVudCk7XG4gICAgfVxuICB9O1xuXG4gIC8qIE1vdXNldXAgKi9cblxuICBoYW5kbGVNb3VzZXVwID0gKGV2ZW50OiBhbnkpID0+IHtcbiAgICAvLyBUYXBcbiAgICB0aGlzLmRldGVjdFRhcCgpO1xuXG4gICAgdGhpcy5pc01vdXNlZG93biA9IGZhbHNlO1xuICAgIHRoaXMucnVuSGFuZGxlcignbW91c2V1cCcsIGV2ZW50KTtcbiAgICB0aGlzLmV2ZW50VHlwZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmkgPSAwO1xuICB9O1xuXG4gIC8qIFdoZWVsICovXG5cbiAgaGFuZGxlV2hlZWwgPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgIHRoaXMucnVuSGFuZGxlcignd2hlZWwnLCBldmVudCk7XG4gIH07XG5cbiAgLyogUmVzaXplICovXG5cbiAgaGFuZGxlUmVzaXplID0gKGV2ZW50OiBhbnkpID0+IHtcbiAgICB0aGlzLnJ1bkhhbmRsZXIoJ3Jlc2l6ZScsIGV2ZW50KTtcbiAgfTtcblxuICBydW5IYW5kbGVyKGV2ZW50TmFtZTogYW55LCByZXNwb25zZTogYW55KSB7XG4gICAgaWYgKHRoaXMuaGFuZGxlcnNbZXZlbnROYW1lXSkge1xuICAgICAgdGhpcy5oYW5kbGVyc1tldmVudE5hbWVdKHJlc3BvbnNlKTtcbiAgICB9XG4gIH1cblxuICAvKlxuICAgKiBEZXRlY3Rpb25cbiAgICovXG5cbiAgZGV0ZWN0UGFuKHRvdWNoZXM6IGFueSkge1xuICAgIHJldHVybiAoXG4gICAgICAodG91Y2hlcy5sZW5ndGggPT09IDEgJiYgIXRoaXMuZXZlbnRUeXBlKSB8fCB0aGlzLmV2ZW50VHlwZSA9PT0gJ3BhbidcbiAgICApO1xuICB9XG5cbiAgZGV0ZWN0RG91YmxlVGFwKCkge1xuICAgIGlmICh0aGlzLmV2ZW50VHlwZSAhPSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIGNvbnN0IHRhcExlbmd0aCA9IGN1cnJlbnRUaW1lIC0gdGhpcy5sYXN0VGFwO1xuXG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuZG91YmxlVGFwVGltZW91dCk7XG5cbiAgICBpZiAodGFwTGVuZ3RoIDwgdGhpcy5kb3VibGVUYXBNaW5UaW1lb3V0ICYmIHRhcExlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICB0aGlzLmRvdWJsZVRhcFRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLmRvdWJsZVRhcFRpbWVvdXQpO1xuICAgIH0sIHRoaXMuZG91YmxlVGFwTWluVGltZW91dCk7XG5cbiAgICB0aGlzLmxhc3RUYXAgPSBjdXJyZW50VGltZTtcblxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBkZXRlY3RUYXAoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZXZlbnRUeXBlICE9IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgY29uc3QgdGFwTGVuZ3RoID0gY3VycmVudFRpbWUgLSB0aGlzLnRvdWNoc3RhcnRUaW1lO1xuXG4gICAgaWYgKHRhcExlbmd0aCA+IDApIHtcbiAgICAgIGlmICh0YXBMZW5ndGggPCB0aGlzLnRhcE1pblRpbWVvdXQpIHtcbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKCd0YXAnLCBldmVudCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoJ2xvbmd0YXAnLCBldmVudCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZGV0ZWN0UGluY2goZXZlbnQ6IGFueSkge1xuICAgIGNvbnN0IHsgdG91Y2hlcyB9ID0gZXZlbnQ7XG4gICAgcmV0dXJuIChcbiAgICAgICh0b3VjaGVzLmxlbmd0aCA9PT0gMiAmJiB0aGlzLmV2ZW50VHlwZSA9PT0gdW5kZWZpbmVkKSB8fFxuICAgICAgdGhpcy5ldmVudFR5cGUgPT09ICdwaW5jaCdcbiAgICApO1xuICB9XG5cbiAgZGV0ZWN0TGluZWFyU3dpcGUoZXZlbnQ6IGFueSkge1xuICAgIGNvbnN0IHsgdG91Y2hlcyB9ID0gZXZlbnQ7XG5cbiAgICBpZiAodG91Y2hlcykge1xuICAgICAgaWYgKFxuICAgICAgICAodG91Y2hlcy5sZW5ndGggPT09IDEgJiYgIXRoaXMuZXZlbnRUeXBlKSB8fFxuICAgICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ2hvcml6b250YWwtc3dpcGUnIHx8XG4gICAgICAgIHRoaXMuZXZlbnRUeXBlID09PSAndmVydGljYWwtc3dpcGUnXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGluZWFyU3dpcGVUeXBlKGV2ZW50KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKFxuICAgICAgIXRoaXMuZXZlbnRUeXBlIHx8XG4gICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ2hvcml6b250YWwtc3dpcGUnIHx8XG4gICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ3ZlcnRpY2FsLXN3aXBlJ1xuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0TGluZWFyU3dpcGVUeXBlKGV2ZW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgZ2V0TGluZWFyU3dpcGVUeXBlKGV2ZW50OiBhbnkpIHtcbiAgICBpZiAoXG4gICAgICB0aGlzLmV2ZW50VHlwZSAhPT0gJ2hvcml6b250YWwtc3dpcGUnICYmXG4gICAgICB0aGlzLmV2ZW50VHlwZSAhPT0gJ3ZlcnRpY2FsLXN3aXBlJ1xuICAgICkge1xuICAgICAgY29uc3QgbW92ZW1lbnRYID0gTWF0aC5hYnModGhpcy5tb3ZlTGVmdCgwLCBldmVudCkgLSB0aGlzLnN0YXJ0WCk7XG4gICAgICBjb25zdCBtb3ZlbWVudFkgPSBNYXRoLmFicyh0aGlzLm1vdmVUb3AoMCwgZXZlbnQpIC0gdGhpcy5zdGFydFkpO1xuXG4gICAgICBpZiAobW92ZW1lbnRZICogMyA+IG1vdmVtZW50WCkge1xuICAgICAgICByZXR1cm4gJ3ZlcnRpY2FsLXN3aXBlJztcbiAgICAgIH1cbiAgICAgIHJldHVybiAnaG9yaXpvbnRhbC1zd2lwZSc7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmV2ZW50VHlwZTtcbiAgfVxuXG4gIGdldEVsZW1lbnRQb3NpdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICB9XG5cbiAgZ2V0VG91Y2hzdGFydFBvc2l0aW9uKGV2ZW50OiBhbnkpIHtcbiAgICB0aGlzLnN0YXJ0WCA9IGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WCAtIHRoaXMuZWxlbWVudFBvc2l0aW9uLmxlZnQ7XG4gICAgdGhpcy5zdGFydFkgPSBldmVudC50b3VjaGVzWzBdLmNsaWVudFkgLSB0aGlzLmVsZW1lbnRQb3NpdGlvbi50b3A7XG4gIH1cblxuICBnZXRNb3VzZWRvd25Qb3NpdGlvbihldmVudDogYW55KSB7XG4gICAgdGhpcy5zdGFydFggPSBldmVudC5jbGllbnRYIC0gdGhpcy5lbGVtZW50UG9zaXRpb24ubGVmdDtcbiAgICB0aGlzLnN0YXJ0WSA9IGV2ZW50LmNsaWVudFkgLSB0aGlzLmVsZW1lbnRQb3NpdGlvbi50b3A7XG4gIH1cblxuICBtb3ZlTGVmdChpbmRleDogYW55LCBldmVudDogYW55KSB7XG4gICAgY29uc3QgeyB0b3VjaGVzIH0gPSBldmVudDtcblxuICAgIGlmICh0b3VjaGVzKSB7XG4gICAgICByZXR1cm4gdG91Y2hlc1tpbmRleF0uY2xpZW50WCAtIHRoaXMuZWxlbWVudFBvc2l0aW9uLmxlZnQ7XG4gICAgfVxuICAgIHJldHVybiBldmVudC5jbGllbnRYIC0gdGhpcy5lbGVtZW50UG9zaXRpb24ubGVmdDtcbiAgfVxuXG4gIG1vdmVUb3AoaW5kZXg6IGFueSwgZXZlbnQ6IGFueSkge1xuICAgIGNvbnN0IHsgdG91Y2hlcyB9ID0gZXZlbnQ7XG5cbiAgICBpZiAodG91Y2hlcykge1xuICAgICAgcmV0dXJuIHRvdWNoZXNbaW5kZXhdLmNsaWVudFkgLSB0aGlzLmVsZW1lbnRQb3NpdGlvbi50b3A7XG4gICAgfVxuICAgIHJldHVybiBldmVudC5jbGllbnRZIC0gdGhpcy5lbGVtZW50UG9zaXRpb24udG9wO1xuICB9XG5cbiAgZGV0ZWN0VG91Y2hTY3JlZW4oKSB7XG4gICAgY29uc3QgcHJlZml4ZXMgPSAnIC13ZWJraXQtIC1tb3otIC1vLSAtbXMtICcuc3BsaXQoJyAnKTtcbiAgICBjb25zdCBtcSA9IGZ1bmN0aW9uIChxdWVyeTogYW55KSB7XG4gICAgICByZXR1cm4gd2luZG93Lm1hdGNoTWVkaWEocXVlcnkpLm1hdGNoZXM7XG4gICAgfTtcblxuICAgIGlmICgnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIGluY2x1ZGUgdGhlICdoZWFydHonIGFzIGEgd2F5IHRvIGhhdmUgYSBub24gbWF0Y2hpbmcgTVEgdG8gaGVscCB0ZXJtaW5hdGUgdGhlIGpvaW5cbiAgICAvLyBodHRwczovL2dpdC5pby92em5GSFxuICAgIGNvbnN0IHF1ZXJ5ID0gWycoJywgcHJlZml4ZXMuam9pbigndG91Y2gtZW5hYmxlZCksKCcpLCAnaGVhcnR6JywgJyknXS5qb2luKFxuICAgICAgJydcbiAgICApO1xuICAgIHJldHVybiBtcShxdWVyeSk7XG4gIH1cblxuICAvKiBQdWJsaWMgcHJvcGVydGllcyBhbmQgbWV0aG9kcyAqL1xuICBvbihldmVudDogRXZlbnRUeXBlLCBoYW5kbGVyOiBGdW5jdGlvbikge1xuICAgIGlmIChldmVudCkge1xuICAgICAgdGhpcy5oYW5kbGVyc1tldmVudF0gPSBoYW5kbGVyO1xuICAgIH1cbiAgfVxufVxuIl19