UNPKG

ng2-custom-carousel

Version:

Carousel Component for Angular 2+. Easily customizable, with autoscroll, loop and navigation controls

241 lines 41.5 kB
import { Component, ContentChildren, Directive, ElementRef, Input, ViewChild, ViewChildren, HostListener } from '@angular/core'; import { Ng2CustomCarouselItemDirective } from './ng2-custom-carousel-item.directive'; import { animate, style } from '@angular/animations'; import * as i0 from "@angular/core"; import * as i1 from "@angular/animations"; import * as i2 from "@angular/common"; import * as i3 from "@angular/forms"; export class Ng2CustomCarouselItemElement { } Ng2CustomCarouselItemElement.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: Ng2CustomCarouselItemElement, deps: [], target: i0.ɵɵFactoryTarget.Directive }); Ng2CustomCarouselItemElement.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.3", type: Ng2CustomCarouselItemElement, selector: ".ng2-custom-carousel-item", ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: Ng2CustomCarouselItemElement, decorators: [{ type: Directive, args: [{ selector: '.ng2-custom-carousel-item' }] }] }); export class Ng2CustomCarouselComponent { constructor(builder) { this.builder = builder; this.timing = '250ms ease-in'; this.showControls = true; this.showNavigation = 'radio'; // radio, numbers, none this.autoScroll = 0; // miliseconds this.loop = false; this.slidesN = 0; this.scrollDirection = 'left'; // left, right this.slidesMargin = 0; this.currentSlide = 0; this.currentSlideShown = 0; this.ng2CustomCarouselWrapperStyle = {}; this.navigationIndexes = []; this.scrollLimit = 0; } get currentSlideString() { return this.currentSlideShown.toString(); } set currentSlideString(index) { this.goToSlide(+index + (this.loop ? 2 : 0)); } onResize() { let carouselWidth = 0; while ((this.ng2CustomCarouselCover.nativeElement.offsetWidth >= ((carouselWidth + this.itemWidth) - this.slidesMargin)) && (((carouselWidth + this.itemWidth) - this.slidesMargin) <= ((this.itemWidth * this.slidesN) - this.slidesMargin))) { carouselWidth = carouselWidth + this.itemWidth; } if (this.slidesMargin) { carouselWidth = carouselWidth - this.slidesMargin; } this.ng2CustomCarouselWrapperStyle = { width: carouselWidth + `px`, margin: 'auto' }; // this.ng2carouselControlsStyle = { // width: carouselWidth + `px`, // margin: `1em auto` // }; } goToSlide(indexSlider) { let restart = false; let reend = false; const sliderDif = indexSlider - this.currentSlide; if (sliderDif === 0) { return; } else if (sliderDif > 0) { if ((!this.loop) && ((this.currentSlide + 1) === this.scrollLimit)) { return; } this.currentSlide = this.currentSlide + sliderDif; if ((this.currentSlide >= (this.items.length - this.slidesN)) && (this.loop)) { this.currentSlideShown = (this.items.length - this.slidesN) - 2; } else { this.currentSlideShown = this.currentSlide - (this.loop ? 2 : 0); } if (this.loop) { if (this.currentSlide === ((this.items.length - this.slidesN))) { restart = true; } } } else { if ((!this.loop) && (this.currentSlide === 0)) { return; } this.currentSlide = this.currentSlide + sliderDif; if (this.loop) { if (this.currentSlide < 2) { this.currentSlideShown = this.currentSlide + (this.scrollLimit - 2); } else { this.currentSlideShown = this.currentSlide - 2; } } else { this.currentSlideShown = this.currentSlide; } if (this.loop) { if (this.currentSlide === 0) { reend = true; } } } const offset = this.currentSlide * this.itemWidth; const myAnimation = this.buildAnimation(offset); this.player = myAnimation.create(this.ng2CustomCarousel.nativeElement); this.player.play(); if (restart) { this.player.onDone(() => { this.currentSlide = 1; this.currentSlideShown = (this.items.length - this.slidesN) - 2; const myAnimationAux = this.buildAnimationStart(); this.playerRestart = myAnimationAux.create(this.ng2CustomCarousel.nativeElement); this.playerRestart.play(); }); } if (reend) { this.player.onDone(() => { this.currentSlide = (this.items.length - this.slidesN) - 1; this.currentSlideShown = this.currentSlide - 2; const myAnimationAux = this.buildAnimationEnd(); this.playerReend = myAnimationAux.create(this.ng2CustomCarousel.nativeElement); this.playerReend.play(); }); } this.stopScrool(); this.startScroll(); } buildAnimation(offset) { return this.builder.build([ animate(this.timing, style({ left: `-` + offset + `px` })) ]); } buildAnimationStart() { return this.builder.build([ animate('1ms ease-in', style({ left: `-` + this.itemWidth + `px` })) ]); } buildAnimationEnd() { return this.builder.build([ animate('1ms ease-in', style({ left: `-` + (this.itemWidth * ((this.items.length - this.slidesN) - 1)) + `px` })) ]); } stopScrool() { if (this.autoScroll > 0) { clearInterval(this.intervalTransition); } } startScroll() { if (this.autoScroll > 0) { this.intervalTransition = setInterval(() => { if (this.scrollDirection === 'right') { this.goToSlide(this.currentSlide - 1); } else { this.goToSlide(this.currentSlide + 1); } }, this.autoScroll); } } ngAfterContentInit() { if (this.slidesN === 0) { this.slidesN = this.items.length; } if (this.items.length <= this.slidesN) { this.slidesN = this.items.length; } if (this.items.length < 2) { this.autoScroll = 0; this.showControls = false; this.showNavigation = 'none'; } this.startScroll(); } ngAfterViewInit() { if (this.items.length > 0) { this.scrollLimit = this.items.length; if (!this.loop) { this.scrollLimit = (this.items.length - this.slidesN) + 1; } for (let i = 0; i < this.scrollLimit; i++) { this.navigationIndexes.push(i); } this.itemWidth = this.itemsElements.first.nativeElement.getBoundingClientRect().width + (this.slidesMargin ? this.slidesMargin : 0); this.onResize(); if (this.loop) { const lastSlice = this.items.length - 1; const addedSlices = []; for (let i = 0; i < (this.slidesN - 1); i++) { addedSlices.push(this.items.toArray()[i]); } this.items.reset([this.items.toArray()[lastSlice - 1], this.items.toArray()[lastSlice], this.items.toArray(), addedSlices]); this.currentSlide = 2; this.ng2CustomCarousel.nativeElement.style.left = '-' + (2 * this.itemWidth) + 'px'; } this.ng2CustomCarousel.nativeElement.style.width = ((this.itemWidth * this.items.length) - this.slidesMargin) + `px`; } } ngOnDestroy() { clearTimeout(this.intervalTransition); } } Ng2CustomCarouselComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: Ng2CustomCarouselComponent, deps: [{ token: i1.AnimationBuilder }], target: i0.ɵɵFactoryTarget.Component }); Ng2CustomCarouselComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.3", type: Ng2CustomCarouselComponent, selector: "ng2-custom-carousel", inputs: { timing: "timing", showControls: "showControls", showNavigation: "showNavigation", autoScroll: "autoScroll", loop: "loop", slidesN: "slidesN", scrollDirection: "scrollDirection", slidesMargin: "slidesMargin" }, host: { listeners: { "window:resize": "onResize($event)" } }, queries: [{ propertyName: "items", predicate: Ng2CustomCarouselItemDirective }], viewQueries: [{ propertyName: "ng2CustomCarousel", first: true, predicate: ["ng2CustomCarousel"], descendants: true, static: true }, { propertyName: "ng2CustomCarouselCover", first: true, predicate: ["ng2CustomCarouselCover"], descendants: true, static: true }, { propertyName: "itemsElements", predicate: Ng2CustomCarouselItemElement, descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"ng2-custom-carousel-panel\" #ng2CustomCarouselCover>\n <section class=\"ng2-custom-carousel-wrapper\" [ngStyle]=\"ng2CustomCarouselWrapperStyle\" (mouseenter)=\"stopScrool()\"\n (mouseleave)=\"startScroll()\">\n <ul class=\"ng2-custom-carousel-inner\" #ng2CustomCarousel>\n <li *ngFor=\"let item of items;\" class=\"ng2-custom-carousel-item\"\n [ngStyle]=\"{'marginRight': slidesMargin + 'px'}\">\n <ng-container [ngTemplateOutlet]=\"item !== undefined?item.tpl:items.last.tpl\"></ng-container>\n </li>\n </ul>\n </section>\n <div class=\"ng2-custom-carousel-controls-wrapper\">\n <div class=\"ng2-custom-carousel-controls\">\n <button *ngIf=\"showControls\" (click)=\"goToSlide(currentSlide - 1)\">Prev</button>\n <div *ngIf=\"showNavigation === 'numbers'\" class=\"ng2-custom-carousel-navigation\">\n <button *ngFor=\"let item of navigationIndexes, let i = index\" (click)=\"goToSlide(i + (loop? 2 : 0))\"\n [class.ng2CustomCarouselSlideSelected]=\"i === currentSlideShown\">{{i + 1}}</button>\n </div>\n <form #searchPackDiscountForm=\"ngForm\" *ngIf=\"showNavigation === 'radio'\"\n class=\"ng2-custom-carousel-navigation\">\n <input *ngFor=\"let item of navigationIndexes, let i = index\" type=\"radio\" name=\"currentSlideShown\"\n [(ngModel)]=\"currentSlideString\" value=\"{{i}}\">\n </form>\n <button *ngIf=\"showControls\" (click)=\"goToSlide(currentSlide + 1)\">Next</button>\n </div>\n </div>\n</div>", styles: [".ng2-custom-carousel-panel .ng2-custom-carousel-wrapper{overflow:hidden}.ng2-custom-carousel-panel .ng2-custom-carousel-wrapper .ng2-custom-carousel-inner{position:relative;display:flex;list-style:none;margin:0;padding:0}.ng2-custom-carousel-panel .ng2-custom-carousel-controls-wrapper{margin:1em auto}.ng2-custom-carousel-panel .ng2-custom-carousel-controls-wrapper .ng2-custom-carousel-controls{margin:auto;width:max-content}.ng2-custom-carousel-panel .ng2-custom-carousel-controls-wrapper .ng2-custom-carousel-controls .ng2-custom-carousel-navigation{display:inline;margin:0 20px}.ng2-custom-carousel-panel .ng2-custom-carousel-controls-wrapper .ng2-custom-carousel-controls .ng2-custom-carousel-slide-selected{background-color:gray}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: Ng2CustomCarouselItemElement, selector: ".ng2-custom-carousel-item" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: Ng2CustomCarouselComponent, decorators: [{ type: Component, args: [{ selector: 'ng2-custom-carousel', template: "<div class=\"ng2-custom-carousel-panel\" #ng2CustomCarouselCover>\n <section class=\"ng2-custom-carousel-wrapper\" [ngStyle]=\"ng2CustomCarouselWrapperStyle\" (mouseenter)=\"stopScrool()\"\n (mouseleave)=\"startScroll()\">\n <ul class=\"ng2-custom-carousel-inner\" #ng2CustomCarousel>\n <li *ngFor=\"let item of items;\" class=\"ng2-custom-carousel-item\"\n [ngStyle]=\"{'marginRight': slidesMargin + 'px'}\">\n <ng-container [ngTemplateOutlet]=\"item !== undefined?item.tpl:items.last.tpl\"></ng-container>\n </li>\n </ul>\n </section>\n <div class=\"ng2-custom-carousel-controls-wrapper\">\n <div class=\"ng2-custom-carousel-controls\">\n <button *ngIf=\"showControls\" (click)=\"goToSlide(currentSlide - 1)\">Prev</button>\n <div *ngIf=\"showNavigation === 'numbers'\" class=\"ng2-custom-carousel-navigation\">\n <button *ngFor=\"let item of navigationIndexes, let i = index\" (click)=\"goToSlide(i + (loop? 2 : 0))\"\n [class.ng2CustomCarouselSlideSelected]=\"i === currentSlideShown\">{{i + 1}}</button>\n </div>\n <form #searchPackDiscountForm=\"ngForm\" *ngIf=\"showNavigation === 'radio'\"\n class=\"ng2-custom-carousel-navigation\">\n <input *ngFor=\"let item of navigationIndexes, let i = index\" type=\"radio\" name=\"currentSlideShown\"\n [(ngModel)]=\"currentSlideString\" value=\"{{i}}\">\n </form>\n <button *ngIf=\"showControls\" (click)=\"goToSlide(currentSlide + 1)\">Next</button>\n </div>\n </div>\n</div>", styles: [".ng2-custom-carousel-panel .ng2-custom-carousel-wrapper{overflow:hidden}.ng2-custom-carousel-panel .ng2-custom-carousel-wrapper .ng2-custom-carousel-inner{position:relative;display:flex;list-style:none;margin:0;padding:0}.ng2-custom-carousel-panel .ng2-custom-carousel-controls-wrapper{margin:1em auto}.ng2-custom-carousel-panel .ng2-custom-carousel-controls-wrapper .ng2-custom-carousel-controls{margin:auto;width:max-content}.ng2-custom-carousel-panel .ng2-custom-carousel-controls-wrapper .ng2-custom-carousel-controls .ng2-custom-carousel-navigation{display:inline;margin:0 20px}.ng2-custom-carousel-panel .ng2-custom-carousel-controls-wrapper .ng2-custom-carousel-controls .ng2-custom-carousel-slide-selected{background-color:gray}\n"] }] }], ctorParameters: function () { return [{ type: i1.AnimationBuilder }]; }, propDecorators: { items: [{ type: ContentChildren, args: [Ng2CustomCarouselItemDirective] }], itemsElements: [{ type: ViewChildren, args: [Ng2CustomCarouselItemElement, { read: ElementRef }] }], ng2CustomCarousel: [{ type: ViewChild, args: ['ng2CustomCarousel', { static: true }] }], ng2CustomCarouselCover: [{ type: ViewChild, args: ['ng2CustomCarouselCover', { static: true }] }], timing: [{ type: Input }], showControls: [{ type: Input }], showNavigation: [{ type: Input }], autoScroll: [{ type: Input }], loop: [{ type: Input }], slidesN: [{ type: Input }], scrollDirection: [{ type: Input }], slidesMargin: [{ type: Input }], onResize: [{ type: HostListener, args: ['window:resize', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmcyLWN1c3RvbS1jYXJvdXNlbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZzItY3VzdG9tLWNhcm91c2VsL3NyYy9saWIvbmcyLWN1c3RvbS1jYXJvdXNlbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZzItY3VzdG9tLWNhcm91c2VsL3NyYy9saWIvbmcyLWN1c3RvbS1jYXJvdXNlbC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUNULGVBQWUsRUFDZixTQUFTLEVBQ1QsVUFBVSxFQUNWLEtBQUssRUFFTCxTQUFTLEVBQ1QsWUFBWSxFQUVaLFlBQVksRUFFYixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUN0RixPQUFPLEVBQUUsT0FBTyxFQUF1RCxLQUFLLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7Ozs7QUFLMUcsTUFBTSxPQUFPLDRCQUE0Qjs7eUhBQTVCLDRCQUE0Qjs2R0FBNUIsNEJBQTRCOzJGQUE1Qiw0QkFBNEI7a0JBSHhDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDJCQUEyQjtpQkFDdEM7O0FBU0QsTUFBTSxPQUFPLDBCQUEwQjtJQUVyQyxZQUFvQixPQUF5QjtRQUF6QixZQUFPLEdBQVAsT0FBTyxDQUFrQjtRQWFwQyxXQUFNLEdBQUcsZUFBZSxDQUFDO1FBQ3pCLGlCQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3BCLG1CQUFjLEdBQUcsT0FBTyxDQUFDLENBQUMsdUJBQXVCO1FBQ2pELGVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQyxjQUFjO1FBQzlCLFNBQUksR0FBRyxLQUFLLENBQUM7UUFDYixZQUFPLEdBQUcsQ0FBQyxDQUFDO1FBQ1osb0JBQWUsR0FBRyxNQUFNLENBQUMsQ0FBQyxjQUFjO1FBQ3hDLGlCQUFZLEdB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QUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBWU4sUUFBUTtzQkFEUCxZQUFZO3VCQUFDLGVBQWUsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkcmVuLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIElucHV0LFxuICBRdWVyeUxpc3QsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0NoaWxkcmVuLFxuICBBZnRlckNvbnRlbnRJbml0LFxuICBIb3N0TGlzdGVuZXIsXG4gIE9uRGVzdHJveVxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgTmcyQ3VzdG9tQ2Fyb3VzZWxJdGVtRGlyZWN0aXZlIH0gZnJvbSAnLi9uZzItY3VzdG9tLWNhcm91c2VsLWl0ZW0uZGlyZWN0aXZlJztcbmltcG9ydCB7IGFuaW1hdGUsIEFuaW1hdGlvbkJ1aWxkZXIsIEFuaW1hdGlvbkZhY3RvcnksIEFuaW1hdGlvblBsYXllciwgc3R5bGUgfSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnLm5nMi1jdXN0b20tY2Fyb3VzZWwtaXRlbSdcbn0pXG5leHBvcnQgY2xhc3MgTmcyQ3VzdG9tQ2Fyb3VzZWxJdGVtRWxlbWVudCB7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25nMi1jdXN0b20tY2Fyb3VzZWwnLFxuICB0ZW1wbGF0ZVVybDogJy4vbmcyLWN1c3RvbS1jYXJvdXNlbC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL25nMi1jdXN0b20tY2Fyb3VzZWwuY29tcG9uZW50LnNhc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBOZzJDdXN0b21DYXJvdXNlbENvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSB7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBidWlsZGVyOiBBbmltYXRpb25CdWlsZGVyKSB7IH1cblxuICBnZXQgY3VycmVudFNsaWRlU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudFNsaWRlU2hvd24udG9TdHJpbmcoKTtcbiAgfVxuXG4gIHNldCBjdXJyZW50U2xpZGVTdHJpbmcoaW5kZXg6IHN0cmluZykge1xuICAgIHRoaXMuZ29Ub1NsaWRlKCtpbmRleCArICh0aGlzLmxvb3AgPyAyIDogMCkpO1xuICB9XG4gIEBDb250ZW50Q2hpbGRyZW4oTmcyQ3VzdG9tQ2Fyb3VzZWxJdGVtRGlyZWN0aXZlKSBpdGVtcyE6IFF1ZXJ5TGlzdDxOZzJDdXN0b21DYXJvdXNlbEl0ZW1EaXJlY3RpdmU+O1xuICBAVmlld0NoaWxkcmVuKE5nMkN1c3RvbUNhcm91c2VsSXRlbUVsZW1lbnQsIHsgcmVhZDogRWxlbWVudFJlZiB9KSBwcml2YXRlIGl0ZW1zRWxlbWVudHMhOiBRdWVyeUxpc3Q8RWxlbWVudFJlZj47XG4gIEBWaWV3Q2hpbGQoJ25nMkN1c3RvbUNhcm91c2VsJywgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSBuZzJDdXN0b21DYXJvdXNlbCE6IEVsZW1lbnRSZWY7XG4gIEBWaWV3Q2hpbGQoJ25nMkN1c3RvbUNhcm91c2VsQ292ZXInLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIG5nMkN1c3RvbUNhcm91c2VsQ292ZXIhOiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSB0aW1pbmcgPSAnMjUwbXMgZWFzZS1pbic7XG4gIEBJbnB1dCgpIHNob3dDb250cm9scyA9IHRydWU7XG4gIEBJbnB1dCgpIHNob3dOYXZpZ2F0aW9uID0gJ3JhZGlvJzsgLy8gcmFkaW8sIG51bWJlcnMsIG5vbmVcbiAgQElucHV0KCkgYXV0b1Njcm9sbCA9IDA7IC8vIG1pbGlzZWNvbmRzXG4gIEBJbnB1dCgpIGxvb3AgPSBmYWxzZTtcbiAgQElucHV0KCkgc2xpZGVzTiA9IDA7XG4gIEBJbnB1dCgpIHNjcm9sbERpcmVjdGlvbiA9ICdsZWZ0JzsgLy8gbGVmdCwgcmlnaHRcbiAgQElucHV0KCkgc2xpZGVzTWFyZ2luID0gMDtcbiAgcHJpdmF0ZSBwbGF5ZXIhOiBBbmltYXRpb25QbGF5ZXI7XG4gIHByaXZhdGUgcGxheWVyUmVzdGFydCE6IEFuaW1hdGlvblBsYXllcjtcbiAgcHJpdmF0ZSBwbGF5ZXJSZWVuZCE6IEFuaW1hdGlvblBsYXllcjtcbiAgcHJpdmF0ZSBpdGVtV2lkdGghOiBudW1iZXI7XG4gIHB1YmxpYyBjdXJyZW50U2xpZGUgPSAwO1xuICBwdWJsaWMgY3VycmVudFNsaWRlU2hvd24gPSAwO1xuICBwdWJsaWMgbmcyQ3VzdG9tQ2Fyb3VzZWxXcmFwcGVyU3R5bGUgPSB7fTtcbiAgcHVibGljIG5hdmlnYXRpb25JbmRleGVzOiBudW1iZXJbXSA9IFtdO1xuICBwcml2YXRlIGludGVydmFsVHJhbnNpdGlvbiE6IGFueTtcbiAgcHJpdmF0ZSBzY3JvbGxMaW1pdCA9IDA7XG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnLCBbJyRldmVudCddKVxuICBvblJlc2l6ZSgpIHtcbiAgICBsZXQgY2Fyb3VzZWxXaWR0aCA9IDA7XG5cbiAgICB3aGlsZSAoKHRoaXMubmcyQ3VzdG9tQ2Fyb3VzZWxDb3Zlci5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoID49ICgoY2Fyb3VzZWxXaWR0aCArIHRoaXMuaXRlbVdpZHRoKSAtIHRoaXMuc2xpZGVzTWFyZ2luKSkgJiZcbiAgICAgICgoKGNhcm91c2VsV2lkdGggKyB0aGlzLml0ZW1XaWR0aCkgLSB0aGlzLnNsaWRlc01hcmdpbikgPD0gKCh0aGlzLml0ZW1XaWR0aCAqIHRoaXMuc2xpZGVzTikgLSB0aGlzLnNsaWRlc01hcmdpbikpKSB7XG4gICAgICBjYXJvdXNlbFdpZHRoID0gY2Fyb3VzZWxXaWR0aCArIHRoaXMuaXRlbVdpZHRoO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNsaWRlc01hcmdpbikgeyBjYXJvdXNlbFdpZHRoID0gY2Fyb3VzZWxXaWR0aCAtIHRoaXMuc2xpZGVzTWFyZ2luOyB9XG5cbiAgICB0aGlzLm5nMkN1c3RvbUNhcm91c2VsV3JhcHBlclN0eWxlID0ge1xuICAgICAgd2lkdGg6IGNhcm91c2VsV2lkdGggKyBgcHhgLFxuICAgICAgbWFyZ2luOiAnYXV0bydcbiAgICB9O1xuICAgIC8vIHRoaXMubmcyY2Fyb3VzZWxDb250cm9sc1N0eWxlID0ge1xuICAgIC8vICAgd2lkdGg6IGNhcm91c2VsV2lkdGggKyBgcHhgLFxuICAgIC8vICAgbWFyZ2luOiBgMWVtIGF1dG9gXG4gICAgLy8gfTtcbiAgfVxuXG4gIGdvVG9TbGlkZShpbmRleFNsaWRlcjogbnVtYmVyKSB7XG4gICAgbGV0IHJlc3RhcnQgPSBmYWxzZTtcbiAgICBsZXQgcmVlbmQgPSBmYWxzZTtcbiAgICBjb25zdCBzbGlkZXJEaWYgPSBpbmRleFNsaWRlciAtIHRoaXMuY3VycmVudFNsaWRlO1xuXG4gICAgaWYgKHNsaWRlckRpZiA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSBpZiAoc2xpZGVyRGlmID4gMCkge1xuXG4gICAgICBpZiAoKCF0aGlzLmxvb3ApICYmICgodGhpcy5jdXJyZW50U2xpZGUgKyAxKSA9PT0gdGhpcy5zY3JvbGxMaW1pdCkpIHsgcmV0dXJuOyB9XG5cbiAgICAgIHRoaXMuY3VycmVudFNsaWRlID0gdGhpcy5jdXJyZW50U2xpZGUgKyBzbGlkZXJEaWY7XG4gICAgICBpZiAoKHRoaXMuY3VycmVudFNsaWRlID49ICh0aGlzLml0ZW1zLmxlbmd0aCAtIHRoaXMuc2xpZGVzTikpICYmICh0aGlzLmxvb3ApKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFNsaWRlU2hvd24gPSAodGhpcy5pdGVtcy5sZW5ndGggLSB0aGlzLnNsaWRlc04pIC0gMjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY3VycmVudFNsaWRlU2hvd24gPSB0aGlzLmN1cnJlbnRTbGlkZSAtICh0aGlzLmxvb3AgPyAyIDogMCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmxvb3ApIHtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudFNsaWRlID09PSAoKHRoaXMuaXRlbXMubGVuZ3RoIC0gdGhpcy5zbGlkZXNOKSkpIHtcbiAgICAgICAgICByZXN0YXJ0ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgfSBlbHNlIHtcblxuICAgICAgaWYgKCghdGhpcy5sb29wKSAmJiAodGhpcy5jdXJyZW50U2xpZGUgPT09IDApKSB7IHJldHVybjsgfVxuXG4gICAgICB0aGlzLmN1cnJlbnRTbGlkZSA9IHRoaXMuY3VycmVudFNsaWRlICsgc2xpZGVyRGlmO1xuXG4gICAgICBpZiAodGhpcy5sb29wKSB7XG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRTbGlkZSA8IDIpIHtcbiAgICAgICAgICB0aGlzLmN1cnJlbnRTbGlkZVNob3duID0gdGhpcy5jdXJyZW50U2xpZGUgKyAodGhpcy5zY3JvbGxMaW1pdCAtIDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuY3VycmVudFNsaWRlU2hvd24gPSB0aGlzLmN1cnJlbnRTbGlkZSAtIDI7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7IHRoaXMuY3VycmVudFNsaWRlU2hvd24gPSB0aGlzLmN1cnJlbnRTbGlkZTsgfVxuXG4gICAgICBpZiAodGhpcy5sb29wKSB7XG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRTbGlkZSA9PT0gMCkge1xuICAgICAgICAgIHJlZW5kID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG9mZnNldCA9IHRoaXMuY3VycmVudFNsaWRlICogdGhpcy5pdGVtV2lkdGg7XG4gICAgY29uc3QgbXlBbmltYXRpb246IEFuaW1hdGlvbkZhY3RvcnkgPSB0aGlzLmJ1aWxkQW5pbWF0aW9uKG9mZnNldCk7XG4gICAgdGhpcy5wbGF5ZXIgPSBteUFuaW1hdGlvbi5jcmVhdGUodGhpcy5uZzJDdXN0b21DYXJvdXNlbC5uYXRpdmVFbGVtZW50KTtcbiAgICB0aGlzLnBsYXllci5wbGF5KCk7XG5cbiAgICBpZiAocmVzdGFydCkge1xuICAgICAgdGhpcy5wbGF5ZXIub25Eb25lKCgpID0+IHtcbiAgICAgICAgdGhpcy5jdXJyZW50U2xpZGUgPSAxO1xuICAgICAgICB0aGlzLmN1cnJlbnRTbGlkZVNob3duID0gKHRoaXMuaXRlbXMubGVuZ3RoIC0gdGhpcy5zbGlkZXNOKSAtIDI7XG4gICAgICAgIGNvbnN0IG15QW5pbWF0aW9uQXV4OiBBbmltYXRpb25GYWN0b3J5ID0gdGhpcy5idWlsZEFuaW1hdGlvblN0YXJ0KCk7XG4gICAgICAgIHRoaXMucGxheWVyUmVzdGFydCA9IG15QW5pbWF0aW9uQXV4LmNyZWF0ZSh0aGlzLm5nMkN1c3RvbUNhcm91c2VsLm5hdGl2ZUVsZW1lbnQpO1xuICAgICAgICB0aGlzLnBsYXllclJlc3RhcnQucGxheSgpO1xuICAgICAgfSk7XG5cbiAgICB9XG5cbiAgICBpZiAocmVlbmQpIHtcbiAgICAgIHRoaXMucGxheWVyLm9uRG9uZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuY3VycmVudFNsaWRlID0gKHRoaXMuaXRlbXMubGVuZ3RoIC0gdGhpcy5zbGlkZXNOKSAtIDE7XG4gICAgICAgIHRoaXMuY3VycmVudFNsaWRlU2hvd24gPSB0aGlzLmN1cnJlbnRTbGlkZSAtIDI7XG4gICAgICAgIGNvbnN0IG15QW5pbWF0aW9uQXV4OiBBbmltYXRpb25GYWN0b3J5ID0gdGhpcy5idWlsZEFuaW1hdGlvbkVuZCgpO1xuICAgICAgICB0aGlzLnBsYXllclJlZW5kID0gbXlBbmltYXRpb25BdXguY3JlYXRlKHRoaXMubmcyQ3VzdG9tQ2Fyb3VzZWwubmF0aXZlRWxlbWVudCk7XG4gICAgICAgIHRoaXMucGxheWVyUmVlbmQucGxheSgpO1xuICAgICAgfSk7XG5cbiAgICB9XG5cbiAgICB0aGlzLnN0b3BTY3Jvb2woKTtcbiAgICB0aGlzLnN0YXJ0U2Nyb2xsKCk7XG5cbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRBbmltYXRpb24ob2Zmc2V0OiBudW1iZXIpIHtcbiAgICByZXR1cm4gdGhpcy5idWlsZGVyLmJ1aWxkKFtcbiAgICAgIGFuaW1hdGUodGhpcy50aW1pbmcsIHN0eWxlKHsgbGVmdDogYC1gICsgb2Zmc2V0ICsgYHB4YCB9KSlcbiAgICBdKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRBbmltYXRpb25TdGFydCgpIHtcbiAgICByZXR1cm4gdGhpcy5idWlsZGVyLmJ1aWxkKFtcbiAgICAgIGFuaW1hdGUoJzFtcyBlYXNlLWluJywgc3R5bGUoeyBsZWZ0OiBgLWAgKyB0aGlzLml0ZW1XaWR0aCArIGBweGAgfSkpXG4gICAgXSk7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkQW5pbWF0aW9uRW5kKCkge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkZXIuYnVpbGQoW1xuICAgICAgYW5pbWF0ZSgnMW1zIGVhc2UtaW4nLCBzdHlsZSh7IGxlZnQ6IGAtYCArICh0aGlzLml0ZW1XaWR0aCAqICgodGhpcy5pdGVtcy5sZW5ndGggLSB0aGlzLnNsaWRlc04pIC0gMSkpICsgYHB4YCB9KSlcbiAgICBdKTtcbiAgfVxuXG4gIHB1YmxpYyBzdG9wU2Nyb29sKCkge1xuICAgIGlmICh0aGlzLmF1dG9TY3JvbGwgPiAwKSB7XG4gICAgICBjbGVhckludGVydmFsKHRoaXMuaW50ZXJ2YWxUcmFuc2l0aW9uKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgc3RhcnRTY3JvbGwoKSB7XG4gICAgaWYgKHRoaXMuYXV0b1Njcm9sbCA+IDApIHtcbiAgICAgIHRoaXMuaW50ZXJ2YWxUcmFuc2l0aW9uID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5zY3JvbGxEaXJlY3Rpb24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICB0aGlzLmdvVG9TbGlkZSh0aGlzLmN1cnJlbnRTbGlkZSAtIDEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZ29Ub1NsaWRlKHRoaXMuY3VycmVudFNsaWRlICsgMSk7XG4gICAgICAgIH1cbiAgICAgIH0sIHRoaXMuYXV0b1Njcm9sbCk7XG4gICAgfVxuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgIGlmICh0aGlzLnNsaWRlc04gPT09IDApIHsgdGhpcy5zbGlkZXNOID0gdGhpcy5pdGVtcy5sZW5ndGg7IH1cblxuICAgIGlmICh0aGlzLml0ZW1zLmxlbmd0aCA8PSB0aGlzLnNsaWRlc04pIHtcbiAgICAgIHRoaXMuc2xpZGVzTiA9IHRoaXMuaXRlbXMubGVuZ3RoO1xuICAgIH1cblxuICAgIGlmICh0aGlzLml0ZW1zLmxlbmd0aCA8IDIpIHtcbiAgICAgIHRoaXMuYXV0b1Njcm9sbCA9IDA7XG4gICAgICB0aGlzLnNob3dDb250cm9scyA9IGZhbHNlO1xuICAgICAgdGhpcy5zaG93TmF2aWdhdGlvbiA9ICdub25lJztcbiAgICB9XG4gICAgdGhpcy5zdGFydFNjcm9sbCgpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuXG4gICAgaWYgKHRoaXMuaXRlbXMubGVuZ3RoID4gMCkge1xuXG4gICAgICB0aGlzLnNjcm9sbExpbWl0ID0gdGhpcy5pdGVtcy5sZW5ndGg7XG4gICAgICBpZiAoIXRoaXMubG9vcCkgeyB0aGlzLnNjcm9sbExpbWl0ID0gKHRoaXMuaXRlbXMubGVuZ3RoIC0gdGhpcy5zbGlkZXNOKSArIDE7IH1cblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNjcm9sbExpbWl0OyBpKyspIHsgdGhpcy5uYXZpZ2F0aW9uSW5kZXhlcy5wdXNoKGkpOyB9XG5cbiAgICAgIHRoaXMuaXRlbVdpZHRoID0gdGhpcy5pdGVtc0VsZW1lbnRzLmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggKyAodGhpcy5zbGlkZXNNYXJnaW4gPyB0aGlzLnNsaWRlc01hcmdpbiA6IDApO1xuXG4gICAgICB0aGlzLm9uUmVzaXplKCk7XG5cbiAgICAgIGlmICh0aGlzLmxvb3ApIHtcbiAgICAgICAgY29uc3QgbGFzdFNsaWNlID0gdGhpcy5pdGVtcy5sZW5ndGggLSAxO1xuICAgICAgICBjb25zdCBhZGRlZFNsaWNlcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8ICh0aGlzLnNsaWRlc04gLSAxKTsgaSsrKSB7XG4gICAgICAgICAgYWRkZWRTbGljZXMucHVzaCh0aGlzLml0ZW1zLnRvQXJyYXkoKVtpXSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pdGVtcy5yZXNldChbdGhpcy5pdGVtcy50b0FycmF5KClbbGFzdFNsaWNlIC0gMV0sIHRoaXMuaXRlbXMudG9BcnJheSgpW2xhc3RTbGljZV0sIHRoaXMuaXRlbXMudG9BcnJheSgpLCBhZGRlZFNsaWNlc10pO1xuXG4gICAgICAgIHRoaXMuY3VycmVudFNsaWRlID0gMjtcbiAgICAgICAgdGhpcy5uZzJDdXN0b21DYXJvdXNlbC5uYXRpdmVFbGVtZW50LnN0eWxlLmxlZnQgPSAnLScgKyAoMiAqIHRoaXMuaXRlbVdpZHRoKSArICdweCc7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubmcyQ3VzdG9tQ2Fyb3VzZWwubmF0aXZlRWxlbWVudC5zdHlsZS53aWR0aCA9ICgodGhpcy5pdGVtV2lkdGggKiB0aGlzLml0ZW1zLmxlbmd0aCkgLSB0aGlzLnNsaWRlc01hcmdpbikgKyBgcHhgO1xuXG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuaW50ZXJ2YWxUcmFuc2l0aW9uKTtcbiAgfVxuXG59XG4iLCI8ZGl2IGNsYXNzPVwibmcyLWN1c3RvbS1jYXJvdXNlbC1wYW5lbFwiICNuZzJDdXN0b21DYXJvdXNlbENvdmVyPlxuICAgIDxzZWN0aW9uIGNsYXNzPVwibmcyLWN1c3RvbS1jYXJvdXNlbC13cmFwcGVyXCIgW25nU3R5bGVdPVwibmcyQ3VzdG9tQ2Fyb3VzZWxXcmFwcGVyU3R5bGVcIiAobW91c2VlbnRlcik9XCJzdG9wU2Nyb29sKClcIlxuICAgICAgICAobW91c2VsZWF2ZSk9XCJzdGFydFNjcm9sbCgpXCI+XG4gICAgICAgIDx1bCBjbGFzcz1cIm5nMi1jdXN0b20tY2Fyb3VzZWwtaW5uZXJcIiAjbmcyQ3VzdG9tQ2Fyb3VzZWw+XG4gICAgICAgICAgICA8bGkgKm5nRm9yPVwibGV0IGl0ZW0gb2YgaXRlbXM7XCIgY2xhc3M9XCJuZzItY3VzdG9tLWNhcm91c2VsLWl0ZW1cIlxuICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cInsnbWFyZ2luUmlnaHQnOiBzbGlkZXNNYXJnaW4gKyAncHgnfVwiPlxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiaXRlbSAhPT0gdW5kZWZpbmVkP2l0ZW0udHBsOml0ZW1zLmxhc3QudHBsXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICA8L3VsPlxuICAgIDwvc2VjdGlvbj5cbiAgICA8ZGl2IGNsYXNzPVwibmcyLWN1c3RvbS1jYXJvdXNlbC1jb250cm9scy13cmFwcGVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJuZzItY3VzdG9tLWNhcm91c2VsLWNvbnRyb2xzXCI+XG4gICAgICAgICAgICA8YnV0dG9uICpuZ0lmPVwic2hvd0NvbnRyb2xzXCIgKGNsaWNrKT1cImdvVG9TbGlkZShjdXJyZW50U2xpZGUgLSAxKVwiPlByZXY8L2J1dHRvbj5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJzaG93TmF2aWdhdGlvbiA9PT0gJ251bWJlcnMnXCIgY2xhc3M9XCJuZzItY3VzdG9tLWNhcm91c2VsLW5hdmlnYXRpb25cIj5cbiAgICAgICAgICAgICAgICA8YnV0dG9uICpuZ0Zvcj1cImxldCBpdGVtIG9mIG5hdmlnYXRpb25JbmRleGVzLCBsZXQgaSA9IGluZGV4XCIgKGNsaWNrKT1cImdvVG9TbGlkZShpICsgKGxvb3A/IDIgOiAwKSlcIlxuICAgICAgICAgICAgICAgICAgICBbY2xhc3MubmcyQ3VzdG9tQ2Fyb3VzZWxTbGlkZVNlbGVjdGVkXT1cImkgPT09IGN1cnJlbnRTbGlkZVNob3duXCI+e3tpICsgMX19PC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxmb3JtICNzZWFyY2hQYWNrRGlzY291bnRGb3JtPVwibmdGb3JtXCIgKm5nSWY9XCJzaG93TmF2aWdhdGlvbiA9PT0gJ3JhZGlvJ1wiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJuZzItY3VzdG9tLWNhcm91c2VsLW5hdmlnYXRpb25cIj5cbiAgICAgICAgICAgICAgICA8aW5wdXQgKm5nRm9yPVwibGV0IGl0ZW0gb2YgbmF2aWdhdGlvbkluZGV4ZXMsIGxldCBpID0gaW5kZXhcIiB0eXBlPVwicmFkaW9cIiBuYW1lPVwiY3VycmVudFNsaWRlU2hvd25cIlxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImN1cnJlbnRTbGlkZVN0cmluZ1wiIHZhbHVlPVwie3tpfX1cIj5cbiAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgICAgIDxidXR0b24gKm5nSWY9XCJzaG93Q29udHJvbHNcIiAoY2xpY2spPVwiZ29Ub1NsaWRlKGN1cnJlbnRTbGlkZSArIDEpXCI+TmV4dDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbjwvZGl2PiJdfQ==