@ciri/ngx-carousel
Version:
A simple angular carousel component.
632 lines • 43.9 kB
JavaScript
/**
* @fileoverview added by tsickle
* Generated from: lib/carousel/carousel.component.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, ElementRef, EventEmitter, forwardRef, Input, Output, QueryList, Renderer2, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { BehaviorSubject, interval, Subject, timer } from 'rxjs';
import { debounceTime, distinctUntilChanged, filter, skip, startWith, takeUntil } from 'rxjs/operators';
import { animationFrame } from 'rxjs/internal/scheduler/animationFrame';
import { CarouselItemComponent } from '../carousel-item/carousel-item.component';
import { CAROUSEL, clamp, inRange } from '../../utils';
var CarouselComponent = /** @class */ (function () {
function CarouselComponent(renderer, hostElRef, cdr) {
this.renderer = renderer;
this.hostElRef = hostElRef;
this.cdr = cdr;
/**
* 是否开启无缝模式
*/
this.loop = false;
/**
* 切换速度(ms)
*/
this.speed = 300;
/**
* 自动轮播时间间隔,0 代表关闭自动轮播
*/
this.autoplay = 0;
/**
* 是否跟随手指滑动,设为 false 代表只在松手后进行移动判断
*/
this.followFinger = true;
/**
* 是否允许手动滑动,设为 false 代表只能通过 api 翻页
*/
this.allowTouchMove = true;
/**
* 默认激活项
*/
this.initialIndex = 0;
/**
* lazyRender 模式下预渲染个数,1 代表左右多渲染一个,2 代表左右多渲染两个,...
*/
this.lazyRenderOffset = 0;
/**
* 是否缓存 lazyRender 模式下渲染过的 item,不从 dom 树中删除
*/
this.cache = false;
/**
* 索引变动时触发
*/
this.indexChange = new EventEmitter();
this.active$ = new BehaviorSubject(null);
this.destroy$ = new Subject();
this.percent = 0; // 手指滑动距离所占宽度总和百分比
// 手指滑动距离所占宽度总和百分比
this.offset = 0; // 偏移量(%)
// 偏移量(%)
this.animating = false; // 是否处于过渡效果中
}
Object.defineProperty(CarouselComponent.prototype, "active", {
get: /**
* @return {?}
*/
function () {
return this.active$.value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CarouselComponent.prototype, "count", {
get: /**
* @return {?}
*/
function () {
return (this.items || []).length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CarouselComponent.prototype, "viewport", {
get: /**
* @return {?}
*/
function () {
return this.hostElRef.nativeElement;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CarouselComponent.prototype, "width", {
get: /**
* @return {?}
*/
function () {
return this.viewport.offsetWidth;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CarouselComponent.prototype, "canMove", {
get: /**
* @return {?}
*/
function () {
return this.allowTouchMove && !this.animating;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CarouselComponent.prototype, "data", {
get: /**
* @return {?}
*/
function () {
return {
active: this.active,
count: this.count,
offset: this.offset,
animating: this.animating,
atFirst: this.active === 0,
atLast: this.active === this.count - 1
};
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
CarouselComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () { };
/**
* @return {?}
*/
CarouselComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
var _this = this;
this.items.changes
.pipe(takeUntil(this.destroy$), startWith(null), debounceTime(0, animationFrame))
.subscribe((/**
* @return {?}
*/
function () {
_this.init();
}));
this.active$
.pipe(takeUntil(this.destroy$), skip(1), filter((/**
* @param {?} v
* @return {?}
*/
function (v) { return v !== null && inRange(v, 0, _this.count - 1); })), distinctUntilChanged())
.subscribe((/**
* @param {?} res
* @return {?}
*/
function (res) {
_this.indexChange.emit(res);
_this.cdr.markForCheck();
}));
// resize 功能待开发
// resize(this.viewport)
// .pipe(takeUntil(this.destroy$), debounceTime(0, animationFrame))
// .subscribe(() => {
// // this.updateWidth()
// // this.goTo(this.active, true)
// })
};
/**
* @return {?}
*/
CarouselComponent.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.destroy$.next();
this.destroy$.complete();
};
/**
* @param {?} e
* @return {?}
*/
CarouselComponent.prototype.onPanStart = /**
* @param {?} e
* @return {?}
*/
function (e) {
this.stopAutoplay();
};
/**
* @param {?} e
* @return {?}
*/
CarouselComponent.prototype.onPanMove = /**
* @param {?} e
* @return {?}
*/
function (e) {
if (!this.canMove) {
return;
}
/** @type {?} */
var deltaX = this.getSafeDeltaX(e.deltaX);
this.percent = ((100 / this.count) * deltaX) / this.width;
if (this.followFinger) {
/** @type {?} */
var offset = this.percent - (100 / this.count) * this.active;
this.move(offset, true);
}
};
/**
* @param {?} e
* @return {?}
*/
CarouselComponent.prototype.onPanEnd = /**
* @param {?} e
* @return {?}
*/
function (e) {
if (!this.canMove) {
return;
}
// 轻拂或者滑动距离大于等于一个节点宽度的 50% 才进行跳转
/** @type {?} */
var newActive = this.active;
/** @type {?} */
var isSwipeLeft = e.direction === Hammer.DIRECTION_LEFT && e.velocityX < -0.3;
/** @type {?} */
var isSwipeRight = e.direction === Hammer.DIRECTION_RIGHT && e.velocityX > 0.3;
if (isSwipeLeft || this.percent <= -50 / this.count) {
newActive++;
}
else if (isSwipeRight || this.percent >= 50 / this.count) {
newActive--;
}
this.goTo(newActive);
this.startAutoplay();
};
/**
* @param {?=} target
* @param {?=} immediate
* @return {?}
*/
CarouselComponent.prototype.goTo = /**
* @param {?=} target
* @param {?=} immediate
* @return {?}
*/
function (target, immediate) {
var _this = this;
if (target === void 0) { target = 0; }
if (immediate === void 0) { immediate = false; }
if (this.animating) {
return;
}
/** @type {?} */
var active = this.getSafeActive(target);
/** @type {?} */
var realActive = this.getRealActive(active);
this.active$.next(realActive);
// 到达第一个或最后一个时更新镜像节点
if (this.loop && (realActive === 0 || realActive === this.count - 1)) {
this.handleMirrorNodes();
}
this.animating = true;
this.move(-(100 / this.count) * active, immediate).subscribe((/**
* @return {?}
*/
function () {
_this.animating = false;
if (active === -1 || active === _this.count) {
_this.goTo(realActive, true);
}
}));
};
/**
* @return {?}
*/
CarouselComponent.prototype.prev = /**
* @return {?}
*/
function () {
this.goTo(this.active - 1);
};
/**
* @return {?}
*/
CarouselComponent.prototype.next = /**
* @return {?}
*/
function () {
this.goTo(this.active + 1);
};
/**
* @private
* @return {?}
*/
CarouselComponent.prototype.init = /**
* @private
* @return {?}
*/
function () {
var _this = this;
if (this.items.length === 0) {
return;
}
this.items.forEach((/**
* @param {?} el
* @param {?} index
* @return {?}
*/
function (el, index) {
el.index = index;
_this.renderer.setStyle(el.elRef.nativeElement, 'width', _this.width + "px");
}));
this.goTo(this.getSafeActive(this.initialIndex, true), true);
this.startAutoplay();
};
/**
* @private
* @param {?} deltaX
* @return {?}
*/
CarouselComponent.prototype.getSafeDeltaX = /**
* @private
* @param {?} deltaX
* @return {?}
*/
function (deltaX) {
/** @type {?} */
var w = this.width;
return clamp(deltaX, -w, w);
};
/**
* @private
* @param {?} active
* @param {?=} strict
* @return {?}
*/
CarouselComponent.prototype.getSafeActive = /**
* @private
* @param {?} active
* @param {?=} strict
* @return {?}
*/
function (active, strict) {
if (strict === void 0) { strict = false; }
/** @type {?} */
var min = this.loop && !strict ? -1 : 0;
/** @type {?} */
var max = this.loop && !strict ? this.count : this.count - 1;
return clamp(active, min, max);
};
// 计算真实索引
// 由于 loop 模式下拷贝了俩节点,所以 active 有误差
// 假设有三个节点,那么 active 非 loop 模式下为 0 ~ 2,loop 模式下为 -1 ~ 3
// 计算真实索引
// 由于 loop 模式下拷贝了俩节点,所以 active 有误差
// 假设有三个节点,那么 active 非 loop 模式下为 0 ~ 2,loop 模式下为 -1 ~ 3
/**
* @private
* @param {?} active
* @return {?}
*/
CarouselComponent.prototype.getRealActive =
// 计算真实索引
// 由于 loop 模式下拷贝了俩节点,所以 active 有误差
// 假设有三个节点,那么 active 非 loop 模式下为 0 ~ 2,loop 模式下为 -1 ~ 3
/**
* @private
* @param {?} active
* @return {?}
*/
function (active) {
return (active + this.count) % this.count;
};
// loop 模式下首尾拷贝一个节点,模拟无缝轮播
// 0 1 2 => 2 0 1 2 0
// TODO: 也许能找到一个不用手动复制 dom,并且可以自动更新内容的方式
// loop 模式下首尾拷贝一个节点,模拟无缝轮播
// 0 1 2 => 2 0 1 2 0
// TODO: 也许能找到一个不用手动复制 dom,并且可以自动更新内容的方式
/**
* @private
* @return {?}
*/
CarouselComponent.prototype.handleMirrorNodes =
// loop 模式下首尾拷贝一个节点,模拟无缝轮播
// 0 1 2 => 2 0 1 2 0
// TODO: 也许能找到一个不用手动复制 dom,并且可以自动更新内容的方式
/**
* @private
* @return {?}
*/
function () {
/** @type {?} */
var trackEl = this.track.nativeElement
// 清理镜像节点
;
// 清理镜像节点
try {
this.renderer.removeChild(trackEl, this.preMirrorNode);
this.renderer.removeChild(trackEl, this.postMirrorNode);
}
catch (e) { }
var _a = this.items, first = _a.first, last = _a.last;
this.preMirrorNode = last.elRef.nativeElement.cloneNode(true);
this.postMirrorNode = first.elRef.nativeElement.cloneNode(true);
this.renderer.addClass(this.preMirrorNode, 'pre-mirror-node');
this.renderer.addClass(this.postMirrorNode, 'post-mirror-node');
this.renderer.insertBefore(trackEl, this.preMirrorNode, first.elRef.nativeElement);
this.renderer.appendChild(trackEl, this.postMirrorNode);
};
/**
* @private
* @param {?} offset
* @param {?=} immediate
* @return {?}
*/
CarouselComponent.prototype.move = /**
* @private
* @param {?} offset
* @param {?=} immediate
* @return {?}
*/
function (offset, immediate) {
if (immediate === void 0) { immediate = false; }
/** @type {?} */
var el = this.track.nativeElement;
/** @type {?} */
var oldOffset = this.offset;
/** @type {?} */
var newOffset = (this.offset = offset);
this.renderer.setStyle(el, 'transition', immediate ? 'none' : "transform " + this.speed + "ms");
this.renderer.setStyle(el, 'transform', "translate3d(" + offset + "%, 0, 0)");
return timer(immediate || newOffset === oldOffset ? 0 : this.speed).pipe(takeUntil(this.destroy$));
};
/**
* @private
* @return {?}
*/
CarouselComponent.prototype.startAutoplay = /**
* @private
* @return {?}
*/
function () {
var _this = this;
if (!this.autoplay || this.count <= 1) {
return;
}
this.stopAutoplay();
this.intervalSub = interval(this.autoplay + this.speed)
.pipe(takeUntil(this.destroy$))
.subscribe((/**
* @return {?}
*/
function () {
/** @type {?} */
var oldActive = _this.active;
/** @type {?} */
var newActive = _this.loop ? oldActive + 1 : _this.getRealActive(oldActive + 1);
_this.goTo(newActive);
}));
};
/**
* @private
* @return {?}
*/
CarouselComponent.prototype.stopAutoplay = /**
* @private
* @return {?}
*/
function () {
this.intervalSub && this.intervalSub.unsubscribe();
};
CarouselComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-carousel',
template: "<div\n class=\"ngx-carousel__track\"\n #track\n (dragstart)=\"$event.preventDefault()\"\n (panstart)=\"onPanStart($event)\"\n (panmove)=\"onPanMove($event)\"\n (panend)=\"onPanEnd($event)\"\n (pancancel)=\"onPanEnd($event)\"\n>\n <ng-content></ng-content>\n</div>\n\n<div class=\"ngx-carousel__indicator\" *ngIf=\"!indicator\">\n <div\n *ngFor=\"let item of items; let i = index\"\n [class.active]=\"i === active\"\n ></div>\n</div>\n\n<ng-container *ngTemplateOutlet=\"indicator; context: { $implicit: data }\"></ng-container>\n",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[class.ngx-carousel]': "true"
},
providers: [
{
provide: CAROUSEL,
useExisting: forwardRef((/**
* @return {?}
*/
function () { return CarouselComponent; }))
}
],
styles: [".ngx-carousel{position:relative;display:block;overflow:hidden}.ngx-carousel__track{position:relative;display:inline-block;white-space:nowrap}.ngx-carousel__indicator{position:absolute;bottom:10px;width:100%;text-align:center;white-space:nowrap;font-size:0;pointer-events:none}.ngx-carousel__indicator div{display:inline-block;width:6px;height:6px;margin:0 3px;border-radius:50%;background:rgba(0,0,0,.25);pointer-events:auto}.ngx-carousel__indicator div.active{background:rgba(0,0,0,.75)}"]
}] }
];
/** @nocollapse */
CarouselComponent.ctorParameters = function () { return [
{ type: Renderer2 },
{ type: ElementRef },
{ type: ChangeDetectorRef }
]; };
CarouselComponent.propDecorators = {
loop: [{ type: Input }],
speed: [{ type: Input }],
autoplay: [{ type: Input }],
followFinger: [{ type: Input }],
allowTouchMove: [{ type: Input }],
indicator: [{ type: Input }],
initialIndex: [{ type: Input }],
lazyRenderOffset: [{ type: Input }],
cache: [{ type: Input }],
indexChange: [{ type: Output }],
track: [{ type: ViewChild, args: ['track', { static: false },] }],
items: [{ type: ContentChildren, args: [CarouselItemComponent,] }]
};
return CarouselComponent;
}());
export { CarouselComponent };
if (false) {
/**
* 是否开启无缝模式
* @type {?}
*/
CarouselComponent.prototype.loop;
/**
* 切换速度(ms)
* @type {?}
*/
CarouselComponent.prototype.speed;
/**
* 自动轮播时间间隔,0 代表关闭自动轮播
* @type {?}
*/
CarouselComponent.prototype.autoplay;
/**
* 是否跟随手指滑动,设为 false 代表只在松手后进行移动判断
* @type {?}
*/
CarouselComponent.prototype.followFinger;
/**
* 是否允许手动滑动,设为 false 代表只能通过 api 翻页
* @type {?}
*/
CarouselComponent.prototype.allowTouchMove;
/**
* 自定义指示器
* @type {?}
*/
CarouselComponent.prototype.indicator;
/**
* 默认激活项
* @type {?}
*/
CarouselComponent.prototype.initialIndex;
/**
* lazyRender 模式下预渲染个数,1 代表左右多渲染一个,2 代表左右多渲染两个,...
* @type {?}
*/
CarouselComponent.prototype.lazyRenderOffset;
/**
* 是否缓存 lazyRender 模式下渲染过的 item,不从 dom 树中删除
* @type {?}
*/
CarouselComponent.prototype.cache;
/**
* 索引变动时触发
* @type {?}
*/
CarouselComponent.prototype.indexChange;
/** @type {?} */
CarouselComponent.prototype.track;
/** @type {?} */
CarouselComponent.prototype.items;
/** @type {?} */
CarouselComponent.prototype.active$;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.destroy$;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.intervalSub;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.percent;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.offset;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.animating;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.preMirrorNode;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.postMirrorNode;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.renderer;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.hostElRef;
/**
* @type {?}
* @private
*/
CarouselComponent.prototype.cdr;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGNpcmkvbmd4LWNhcm91c2VsLyIsInNvdXJjZXMiOlsibGliL2Nhcm91c2VsL2Nhcm91c2VsLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFFTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxlQUFlLEVBQ2YsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsS0FBSyxFQUdMLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUVULFdBQVcsRUFDWCxTQUFTLEVBQ1QsaUJBQWlCLEVBQ2xCLE1BQU0sZUFBZSxDQUFBO0FBQ3RCLE9BQU8sRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBZ0IsS0FBSyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBQzlFLE9BQU8sRUFDTCxZQUFZLEVBQ1osb0JBQW9CLEVBQ3BCLE1BQU0sRUFDTixJQUFJLEVBQ0osU0FBUyxFQUNULFNBQVMsRUFDVixNQUFNLGdCQUFnQixDQUFBO0FBQ3ZCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQTtBQUV2RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQTtBQUNoRixPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQVUsTUFBTSxhQUFhLENBQUE7QUFFOUQ7SUFpRkUsMkJBQ1UsUUFBbUIsRUFDbkIsU0FBcUIsRUFDckIsR0FBc0I7UUFGdEIsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUNuQixjQUFTLEdBQVQsU0FBUyxDQUFZO1FBQ3JCLFFBQUcsR0FBSCxHQUFHLENBQW1COzs7O1FBbEV2QixTQUFJLEdBQVksS0FBSyxDQUFBOzs7O1FBRXJCLFVBQUssR0FBVyxHQUFHLENBQUE7Ozs7UUFFbkIsYUFBUSxHQUFXLENBQUMsQ0FBQTs7OztRQUVwQixpQkFBWSxHQUFZLElBQUksQ0FB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QTZCOzs7OztJQUM3QixnQ0FBOEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkcmVuLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBRdWVyeUxpc3QsXG4gIFJlbmRlcmVyMixcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0VuY2Fwc3VsYXRpb25cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgaW50ZXJ2YWwsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiwgdGltZXIgfSBmcm9tICdyeGpzJ1xuaW1wb3J0IHtcbiAgZGVib3VuY2VUaW1lLFxuICBkaXN0aW5jdFVudGlsQ2hhbmdlZCxcbiAgZmlsdGVyLFxuICBza2lwLFxuICBzdGFydFdpdGgsXG4gIHRha2VVbnRpbFxufSBmcm9tICdyeGpzL29wZXJhdG9ycydcbmltcG9ydCB7IGFuaW1hdGlvbkZyYW1lIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9zY2hlZHVsZXIvYW5pbWF0aW9uRnJhbWUnXG5pbXBvcnQgeyBDYXJvdXNlbERhdGEgfSBmcm9tICcuLi9jYXJvdXNlbC5tb2RlbCdcbmltcG9ydCB7IENhcm91c2VsSXRlbUNvbXBvbmVudCB9IGZyb20gJy4uL2Nhcm91c2VsLWl0ZW0vY2Fyb3VzZWwtaXRlbS5jb21wb25lbnQnXG5pbXBvcnQgeyBDQVJPVVNFTCwgY2xhbXAsIGluUmFuZ2UsIHJlc2l6ZSB9IGZyb20gJy4uLy4uL3V0aWxzJ1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtY2Fyb3VzZWwnLFxuICB0ZW1wbGF0ZVVybDogJy4vY2Fyb3VzZWwuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jYXJvdXNlbC5jb21wb25lbnQubGVzcyddLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaG9zdDoge1xuICAgICdbY2xhc3Mubmd4LWNhcm91c2VsXSc6IGB0cnVlYFxuICB9LFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBDQVJPVVNFTCxcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IENhcm91c2VsQ29tcG9uZW50KVxuICAgIH1cbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBDYXJvdXNlbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgLyoqIOaYr+WQpuW8gOWQr+aXoOe8neaooeW8jyAqL1xuICBASW5wdXQoKSBsb29wOiBib29sZWFuID0gZmFsc2VcbiAgLyoqIOWIh+aNoumAn+W6pu+8iG1z77yJICovXG4gIEBJbnB1dCgpIHNwZWVkOiBudW1iZXIgPSAzMDBcbiAgLyoqIOiHquWKqOi9ruaSreaXtumXtOmXtOmalO+8jDAg5Luj6KGo5YWz6Zet6Ieq5Yqo6L2u5pKtICovXG4gIEBJbnB1dCgpIGF1dG9wbGF5OiBudW1iZXIgPSAwXG4gIC8qKiDmmK/lkKbot5/pmo/miYvmjIfmu5HliqjvvIzorr7kuLogZmFsc2Ug5Luj6KGo5Y+q5Zyo5p2+5omL5ZCO6L+b6KGM56e75Yqo5Yik5patICovXG4gIEBJbnB1dCgpIGZvbGxvd0ZpbmdlcjogYm9vbGVhbiA9IHRydWVcbiAgLyoqIOaYr+WQpuWFgeiuuOaJi+WKqOa7keWKqO+8jOiuvuS4uiBmYWxzZSDku6Pooajlj6rog73pgJrov4cgYXBpIOe/u+mhtSAqL1xuICBASW5wdXQoKSBhbGxvd1RvdWNoTW92ZTogYm9vbGVhbiA9IHRydWVcbiAgLyoqIOiHquWumuS5ieaMh+ekuuWZqCAqL1xuICBASW5wdXQoKSBpbmRpY2F0b3I6IFRlbXBsYXRlUmVmPHsgJGltcGxpY2l0OiBDYXJvdXNlbERhdGEgfT5cbiAgLyoqIOm7mOiupOa/gOa0u+mhuSAqL1xuICBASW5wdXQoKSBpbml0aWFsSW5kZXg6IG51bWJlciA9IDBcbiAgLyoqIGxhenlSZW5kZXIg5qih5byP5LiL6aKE5riy5p+T5Liq5pWw77yMMSDku6Pooajlt6blj7PlpJrmuLLmn5PkuIDkuKrvvIwyIOS7o+ihqOW3puWPs+Wkmua4suafk+S4pOS4qu+8jC4uLiAqL1xuICBASW5wdXQoKSBsYXp5UmVuZGVyT2Zmc2V0OiBudW1iZXIgPSAwXG4gIC8qKiDmmK/lkKbnvJPlrZggbGF6eVJlbmRlciDmqKHlvI/kuIvmuLLmn5Pov4fnmoQgaXRlbe+8jOS4jeS7jiBkb20g5qCR5Lit5Yig6ZmkICovXG4gIEBJbnB1dCgpIGNhY2hlOiBib29sZWFuID0gZmFsc2VcblxuICAvKiog57Si5byV5Y+Y5Yqo5pe26Kem5Y+RICovXG4gIEBPdXRwdXQoKSBpbmRleENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpXG5cbiAgQFZpZXdDaGlsZCgndHJhY2snLCB7IHN0YXRpYzogZmFsc2UgfSkgdHJhY2s6IEVsZW1lbnRSZWZcbiAgQENvbnRlbnRDaGlsZHJlbihDYXJvdXNlbEl0ZW1Db21wb25lbnQpIGl0ZW1zOiBRdWVyeUxpc3Q8Q2Fyb3VzZWxJdGVtQ29tcG9uZW50PlxuXG4gIGdldCBhY3RpdmUoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlJC52YWx1ZVxuICB9XG5cbiAgZ2V0IGNvdW50KCkge1xuICAgIHJldHVybiAodGhpcy5pdGVtcyB8fCBbXSkubGVuZ3RoXG4gIH1cblxuICBnZXQgdmlld3BvcnQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaG9zdEVsUmVmLm5hdGl2ZUVsZW1lbnRcbiAgfVxuXG4gIGdldCB3aWR0aCgpIHtcbiAgICByZXR1cm4gdGhpcy52aWV3cG9ydC5vZmZzZXRXaWR0aFxuICB9XG5cbiAgZ2V0IGNhbk1vdmUoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWxsb3dUb3VjaE1vdmUgJiYgIXRoaXMuYW5pbWF0aW5nXG4gIH1cblxuICBnZXQgZGF0YSgpOiBDYXJvdXNlbERhdGEge1xuICAgIHJldHVybiB7XG4gICAgICBhY3RpdmU6IHRoaXMuYWN0aXZlLFxuICAgICAgY291bnQ6IHRoaXMuY291bnQsXG4gICAgICBvZmZzZXQ6IHRoaXMub2Zmc2V0LFxuICAgICAgYW5pbWF0aW5nOiB0aGlzLmFuaW1hdGluZyxcbiAgICAgIGF0Rmlyc3Q6IHRoaXMuYWN0aXZlID09PSAwLFxuICAgICAgYXRMYXN0OiB0aGlzLmFjdGl2ZSA9PT0gdGhpcy5jb3VudCAtIDFcbiAgICB9XG4gIH1cbiAgYWN0aXZlJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPihudWxsKVxuICBwcml2YXRlIGRlc3Ryb3kkID0gbmV3IFN1YmplY3QoKVxuICBwcml2YXRlIGludGVydmFsU3ViOiBTdWJzY3JpcHRpb25cbiAgcHJpdmF0ZSBwZXJjZW50ID0gMCAvLyDmiYvmjIfmu5Hliqjot53nprvmiYDljaDlrr3luqbmgLvlkoznmb7liIbmr5RcbiAgcHJpdmF0ZSBvZmZzZXQgPSAwIC8vIOWBj+enu+mHj++8iCXvvIlcbiAgcHJpdmF0ZSBhbmltYXRpbmcgPSBmYWxzZSAvLyDmmK/lkKblpITkuo7ov4fmuKHmlYjmnpzkuK1cbiAgcHJpdmF0ZSBwcmVNaXJyb3JOb2RlOiBOb2RlIC8vIOWJjemVnOWDj+iKgueCuVxuICBwcml2YXRlIHBvc3RNaXJyb3JOb2RlOiBOb2RlIC8vIOWQjumVnOWDj+iKgueCuVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMixcbiAgICBwcml2YXRlIGhvc3RFbFJlZjogRWxlbWVudFJlZixcbiAgICBwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWZcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCkge31cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5pdGVtcy5jaGFuZ2VzXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCksIHN0YXJ0V2l0aChudWxsKSwgZGVib3VuY2VUaW1lKDAsIGFuaW1hdGlvbkZyYW1lKSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmluaXQoKVxuICAgICAgfSlcblxuICAgIHRoaXMuYWN0aXZlJFxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSxcbiAgICAgICAgc2tpcCgxKSxcbiAgICAgICAgZmlsdGVyKHYgPT4gdiAhPT0gbnVsbCAmJiBpblJhbmdlKHYsIDAsIHRoaXMuY291bnQgLSAxKSksXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKClcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUocmVzID0+IHtcbiAgICAgICAgdGhpcy5pbmRleENoYW5nZS5lbWl0KHJlcylcbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKClcbiAgICAgIH0pXG5cbiAgICAvLyByZXNpemUg5Yqf6IO95b6F5byA5Y+RXG4gICAgLy8gcmVzaXplKHRoaXMudmlld3BvcnQpXG4gICAgLy8gICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCksIGRlYm91bmNlVGltZSgwLCBhbmltYXRpb25GcmFtZSkpXG4gICAgLy8gICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAvLyAgICAgLy8gdGhpcy51cGRhdGVXaWR0aCgpXG4gICAgLy8gICAgIC8vIHRoaXMuZ29Ubyh0aGlzLmFjdGl2ZSwgdHJ1ZSlcbiAgICAvLyAgIH0pXG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKVxuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKVxuICB9XG5cbiAgb25QYW5TdGFydChlOiBIYW1tZXJJbnB1dCkge1xuICAgIHRoaXMuc3RvcEF1dG9wbGF5KClcbiAgfVxuXG4gIG9uUGFuTW92ZShlOiBIYW1tZXJJbnB1dCkge1xuICAgIGlmICghdGhpcy5jYW5Nb3ZlKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgY29uc3QgZGVsdGFYID0gdGhpcy5nZXRTYWZlRGVsdGFYKGUuZGVsdGFYKVxuICAgIHRoaXMucGVyY2VudCA9ICgoMTAwIC8gdGhpcy5jb3VudCkgKiBkZWx0YVgpIC8gdGhpcy53aWR0aFxuXG4gICAgaWYgKHRoaXMuZm9sbG93RmluZ2VyKSB7XG4gICAgICBjb25zdCBvZmZzZXQgPSB0aGlzLnBlcmNlbnQgLSAoMTAwIC8gdGhpcy5jb3VudCkgKiB0aGlzLmFjdGl2ZVxuICAgICAgdGhpcy5tb3ZlKG9mZnNldCwgdHJ1ZSlcbiAgICB9XG4gIH1cblxuICBvblBhbkVuZChlOiBIYW1tZXJJbnB1dCkge1xuICAgIGlmICghdGhpcy5jYW5Nb3ZlKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgLy8g6L275ouC5oiW6ICF5ruR5Yqo6Led56a75aSn5LqO562J5LqO5LiA5Liq6IqC54K55a695bqm55qEIDUwJSDmiY3ov5vooYzot7PovaxcbiAgICBsZXQgbmV3QWN0aXZlID0gdGhpcy5hY3RpdmVcbiAgICBjb25zdCBpc1N3aXBlTGVmdCA9IGUuZGlyZWN0aW9uID09PSBIYW1tZXIuRElSRUNUSU9OX0xFRlQgJiYgZS52ZWxvY2l0eVggPCAtMC4zXG4gICAgY29uc3QgaXNTd2lwZVJpZ2h0ID0gZS5kaXJlY3Rpb24gPT09IEhhbW1lci5ESVJFQ1RJT05fUklHSFQgJiYgZS52ZWxvY2l0eVggPiAwLjNcbiAgICBpZiAoaXNTd2lwZUxlZnQgfHwgdGhpcy5wZXJjZW50IDw9IC01MCAvIHRoaXMuY291bnQpIHtcbiAgICAgIG5ld0FjdGl2ZSsrXG4gICAgfSBlbHNlIGlmIChpc1N3aXBlUmlnaHQgfHwgdGhpcy5wZXJjZW50ID49IDUwIC8gdGhpcy5jb3VudCkge1xuICAgICAgbmV3QWN0aXZlLS1cbiAgICB9XG4gICAgdGhpcy5nb1RvKG5ld0FjdGl2ZSlcbiAgICB0aGlzLnN0YXJ0QXV0b3BsYXkoKVxuICB9XG5cbiAgZ29Ubyh0YXJnZXQgPSAwLCBpbW1lZGlhdGUgPSBmYWxzZSkge1xuICAgIGlmICh0aGlzLmFuaW1hdGluZykge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgYWN0aXZlID0gdGhpcy5nZXRTYWZlQWN0aXZlKHRhcmdldClcbiAgICBjb25zdCByZWFsQWN0aXZlID0gdGhpcy5nZXRSZWFsQWN0aXZlKGFjdGl2ZSlcbiAgICB0aGlzLmFjdGl2ZSQubmV4dChyZWFsQWN0aXZlKVxuXG4gICAgLy8g5Yiw6L6+56ys5LiA5Liq5oiW5pyA5ZCO5LiA5Liq5pe25pu05paw6ZWc5YOP6IqC54K5XG4gICAgaWYgKHRoaXMubG9vcCAmJiAocmVhbEFjdGl2ZSA9PT0gMCB8fCByZWFsQWN0aXZlID09PSB0aGlzLmNvdW50IC0gMSkpIHtcbiAgICAgIHRoaXMuaGFuZGxlTWlycm9yTm9kZXMoKVxuICAgIH1cblxuICAgIHRoaXMuYW5pbWF0aW5nID0gdHJ1ZVxuICAgIHRoaXMubW92ZSgtKDEwMCAvIHRoaXMuY291bnQpICogYWN0aXZlLCBpbW1lZGlhdGUpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLmFuaW1hdGluZyA9IGZhbHNlXG4gICAgICBpZiAoYWN0aXZlID09PSAtMSB8fCBhY3RpdmUgPT09IHRoaXMuY291bnQpIHtcbiAgICAgICAgdGhpcy5nb1RvKHJlYWxBY3RpdmUsIHRydWUpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIHByZXYoKSB7XG4gICAgdGhpcy5nb1RvKHRoaXMuYWN0aXZlIC0gMSlcbiAgfVxuXG4gIG5leHQoKSB7XG4gICAgdGhpcy5nb1RvKHRoaXMuYWN0aXZlICsgMSlcbiAgfVxuXG4gIHByaXZhdGUgaW5pdCgpIHtcbiAgICBpZiAodGhpcy5pdGVtcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB0aGlzLml0ZW1zLmZvckVhY2goKGVsLCBpbmRleCkgPT4ge1xuICAgICAgZWwuaW5kZXggPSBpbmRleFxuICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShlbC5lbFJlZi5uYXRpdmVFbGVtZW50LCAnd2lkdGgnLCBgJHt0aGlzLndpZHRofXB4YClcbiAgICB9KVxuICAgIHRoaXMuZ29Ubyh0aGlzLmdldFNhZmVBY3RpdmUodGhpcy5pbml0aWFsSW5kZXgsIHRydWUpLCB0cnVlKVxuICAgIHRoaXMuc3RhcnRBdXRvcGxheSgpXG4gIH1cblxuICBwcml2YXRlIGdldFNhZmVEZWx0YVgoZGVsdGFYKSB7XG4gICAgY29uc3QgdyA9IHRoaXMud2lkdGhcbiAgICByZXR1cm4gY2xhbXAoZGVsdGFYLCAtdywgdylcbiAgfVxuXG4gIHByaXZhdGUgZ2V0U2FmZUFjdGl2ZShhY3RpdmUsIHN0cmljdCA9IGZhbHNlKSB7XG4gICAgY29uc3QgbWluID0gdGhpcy5sb29wICYmICFzdHJpY3QgPyAtMSA6IDBcbiAgICBjb25zdCBtYXggPSB0aGlzLmxvb3AgJiYgIXN0cmljdCA/IHRoaXMuY291bnQgOiB0aGlzLmNvdW50IC0gMVxuICAgIHJldHVybiBjbGFtcChhY3RpdmUsIG1pbiwgbWF4KVxuICB9XG5cbiAgLy8g6K6h566X55yf5a6e57Si5byVXG4gIC8vIOeUseS6jiBsb29wIOaooeW8j+S4i+aLt+i0neS6huS/qeiKgueCue+8jOaJgOS7pSBhY3RpdmUg5pyJ6K+v5beuXG4gIC8vIOWBh+iuvuacieS4ieS4quiKgueCue+8jOmCo+S5iCBhY3RpdmUg6Z2eIGxvb3Ag5qih5byP5LiL5Li6IDAg772eIDLvvIxsb29wIOaooeW8j+S4i+S4uiAtMSDvvZ4gM1xuICBwcml2YXRlIGdldFJlYWxBY3RpdmUoYWN0aXZlKSB7XG4gICAgcmV0dXJuIChhY3RpdmUgKyB0aGlzLmNvdW50KSAlIHRoaXMuY291bnRcbiAgfVxuXG4gIC8vIGxvb3Ag5qih5byP5LiL6aaW5bC+5ou36LSd5LiA5Liq6IqC54K577yM5qih5ouf5peg57yd6L2u5pKtXG4gIC8vIDAgMSAyID0+IDIgMCAxIDIgMFxuICAvLyBUT0RPOiDkuZ/orrjog73mib7liLDkuIDkuKrkuI3nlKjmiYvliqjlpI3liLYgZG9t77yM5bm25LiU5Y+v5Lul6Ieq5Yqo5pu05paw5YaF5a6555qE5pa55byPXG4gIHByaXZhdGUgaGFuZGxlTWlycm9yTm9kZXMoKSB7XG4gICAgY29uc3QgdHJhY2tFbCA9IHRoaXMudHJhY2submF0aXZlRWxlbWVudFxuICAgIC8vIOa4heeQhumVnOWDj+iKgueCuVxuICAgIHRyeSB7XG4gICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNoaWxkKHRyYWNrRWwsIHRoaXMucHJlTWlycm9yTm9kZSlcbiAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2hpbGQodHJhY2tFbCwgdGhpcy5wb3N0TWlycm9yTm9kZSlcbiAgICB9IGNhdGNoIChlKSB7fVxuXG4gICAgY29uc3QgeyBmaXJzdCwgbGFzdCB9ID0gdGhpcy5pdGVtc1xuICAgIHRoaXMucHJlTWlycm9yTm9kZSA9IGxhc3QuZWxSZWYubmF0aXZlRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSlcbiAgICB0aGlzLnBvc3RNaXJyb3JOb2RlID0gZmlyc3QuZWxSZWYubmF0aXZlRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSlcblxuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5wcmVNaXJyb3JOb2RlLCAncHJlLW1pcnJvci1ub2RlJylcbiAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMucG9zdE1pcnJvck5vZGUsICdwb3N0LW1pcnJvci1ub2RlJylcbiAgICB0aGlzLnJlbmRlcmVyLmluc2VydEJlZm9yZSh0cmFja0VsLCB0aGlzLnByZU1pcnJvck5vZGUsIGZpcnN0LmVsUmVmLm5hdGl2ZUVsZW1lbnQpXG4gICAgdGhpcy5yZW5kZXJlci5hcHBlbmRDaGlsZCh0cmFja0VsLCB0aGlzLnBvc3RNaXJyb3JOb2RlKVxuICB9XG5cbiAgcHJpdmF0ZSBtb3ZlKG9mZnNldCwgaW1tZWRpYXRlID0gZmFsc2UpIHtcbiAgICBjb25zdCBlbCA9IHRoaXMudHJhY2submF0aXZlRWxlbWVudFxuICAgIGNvbnN0IG9sZE9mZnNldCA9IHRoaXMub2Zmc2V0XG4gICAgY29uc3QgbmV3T2Zmc2V0ID0gKHRoaXMub2Zmc2V0ID0gb2Zmc2V0KVxuXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShlbCwgJ3RyYW5zaXRpb24nLCBpbW1lZGlhdGUgPyAnbm9uZScgOiBgdHJhbnNmb3JtICR7dGhpcy5zcGVlZH1tc2ApXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShlbCwgJ3RyYW5zZm9ybScsIGB0cmFuc2xhdGUzZCgke29mZnNldH0lLCAwLCAwKWApXG5cbiAgICByZXR1cm4gdGltZXIoaW1tZWRpYXRlIHx8IG5ld09mZnNldCA9PT0gb2xkT2Zmc2V0ID8gMCA6IHRoaXMuc3BlZWQpLnBpcGUoXG4gICAgICB0YWtlVW50aWwodGhpcy5kZXN0cm95JClcbiAgICApXG4gIH1cblxuICBwcml2YXRlIHN0YXJ0QXV0b3BsYXkoKSB7XG4gICAgaWYgKCF0aGlzLmF1dG9wbGF5IHx8IHRoaXMuY291bnQgPD0gMSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdGhpcy5zdG9wQXV0b3BsYXkoKVxuXG4gICAgdGhpcy5pbnRlcnZhbFN1YiA9IGludGVydmFsKHRoaXMuYXV0b3BsYXkgKyB0aGlzLnNwZWVkKVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIGNvbnN0IG9sZEFjdGl2ZSA9IHRoaXMuYWN0aXZlXG4gICAgICAgIGNvbnN0IG5ld0FjdGl2ZSA9IHRoaXMubG9vcCA/IG9sZEFjdGl2ZSArIDEgOiB0aGlzLmdldFJlYWxBY3RpdmUob2xkQWN0aXZlICsgMSlcbiAgICAgICAgdGhpcy5nb1RvKG5ld0FjdGl2ZSlcbiAgICAgIH0pXG4gIH1cblxuICBwcml2YXRlIHN0b3BBdXRvcGxheSgpIHtcbiAgICB0aGlzLmludGVydmFsU3ViICYmIHRoaXMuaW50ZXJ2YWxTdWIudW5zdWJzY3JpYmUoKVxuICB9XG59XG4iXX0=