UNPKG

@ciri/ngx-carousel

Version:
632 lines 43.9 kB
/** * @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=