ngx-carousel-ease
Version:
ngx-carousel-ease is a versatile Angular library providing a feature-rich, simple, and performant carousel component. This library supports infinite and responsive mode, mouse and touch event. Attention has been put to accessibility, performance, and frie
168 lines • 22.6 kB
JavaScript
import { signal } from '@angular/core';
export class Carousel {
constructor(carousel, maxWidthCarousel, slideToShow, slideWidth, slideMaxWidth, gap, responsive, loop) {
this.carousel = carousel;
this.maxWidthCarousel = maxWidthCarousel;
this.slideToShow = slideToShow;
this.slideWidth = slideWidth;
this.slideMaxWidth = slideMaxWidth;
this.gap = gap;
this.responsive = responsive;
this.loop = loop;
this.numberDots = signal(0);
this.maxScrollableContent = signal(0);
this.arrayNumberDots = signal([]);
this.totalSlides = 0;
this.initialSlideToShow = 1;
this.paddingCarousel = 0;
this.arrayOfSlides = [];
this.init();
}
get carouselElement() {
return this.carousel;
}
init() {
this.paddingCarousel = this.getPaddingCarousel();
this.initialSlideToShow = this.slideToShow;
this.slidesContainer = this.selectSlidesContainer();
this.slides = this.selectSlides();
this.arrayOfSlides = this.slidesToArray();
this.totalSlides = this.slides.length;
this.originalSlideWidth = this.slideWidth;
this.setWidthSlides();
this.setMaxWidthCarousel();
this.updateProperties();
this.slidesContainer.style.gap = `${this.gap}px`;
this.setDraggableImgToFalse();
}
/**
* Set the slide width and max width
* NB: In responsive mode, width is automatically adapted through the setAutoColumnSlideContainer() method.
*
*/
setWidthSlides() {
for (const slide of this.slides) {
slide.style.maxWidth = `${this.slideMaxWidth}px`;
slide.style.width = '100%';
slide.style.userSelect = 'none';
if (!this.responsive) {
slide.style.width = `${this.slideWidth}px`;
}
}
}
/**
* Update carousel properties
* Occurs at start and at resizing.
*/
updateProperties() {
this.carouselWidth = this.carousel.clientWidth;
if (this.responsive) {
this.updateSlideToShowResponsive();
this.setAutoColumnSlideContainer();
}
else {
this.updateSlideToShowNotResponsive();
}
this.numberDots.set(this.setNumberDots());
this.arrayNumberDots.set([...Array(this.numberDots()).keys()]);
this.slideWidthWithGap = this.slideWidth + this.gap;
this.setWidthSlideContainer();
this.maxScrollableContent.set(this.getMaxScroll());
}
/**
* Update slide to show (responsive mode)
* Computes the number of slide fitting
*/
updateSlideToShowResponsive() {
const slideWidthPlusGap = this.originalSlideWidth + this.gap;
const referenceWidth = Math.min(this.carouselWidth, this.maxWidthCarousel || Infinity, window.innerWidth);
const slideFitting = Math.floor(referenceWidth / slideWidthPlusGap) || 1;
this.determineSlideToShow(slideFitting);
}
/**
* Determine slide to show
* Useful to compute the slide displayed on screen and for the slider class.
* In not responsive mode, the maximum slides to show is determined by the maximum available space and the width of the slide set by the user.
*/
determineSlideToShow(slideFitting) {
const maxSlidesToShow = this.responsive
? this.initialSlideToShow
: this.totalSlides;
this.slideToShow = Math.min(slideFitting, maxSlidesToShow);
}
/**
* Update slide to show (not responsive mode)
* Computes the number of slide fitting. The number of slides to be shown are determined by the number of slides fitting within its container.
*/
updateSlideToShowNotResponsive() {
const slideWidthPlusGap = this.slideWidth + this.gap;
const referenceWidth = Math.min(this.carouselWidth, this.maxWidthCarousel || Infinity, window.innerWidth);
const numberOfSlidesComputed = Math.floor(referenceWidth / slideWidthPlusGap) || 1;
const slideFitting = Math.min(numberOfSlidesComputed, this.totalSlides);
this.determineSlideToShow(slideFitting);
}
getPaddingCarousel() {
const computedStyle = window.getComputedStyle(this.carousel);
const paddingLeft = computedStyle.getPropertyValue('padding-left');
const paddingRight = computedStyle.getPropertyValue('padding-right');
return parseFloat(paddingLeft) + parseFloat(paddingRight);
}
setMaxWidthCarousel() {
this.carousel.style.maxWidth = `${this.maxWidthCarousel}px`;
}
/**
* Set the with of a slide, responsive mode
* There are [n cards - 1] gaps (3 cards, 2 gaps)
*/
setAutoColumnSlideContainer() {
const windowWidth = this.carouselWidth -
this.paddingCarousel -
(this.slideToShow - 1) * this.gap;
const widthPerSlide = windowWidth / this.slideToShow;
this.slidesContainer.style.gridAutoColumns = `${widthPerSlide}px`;
this.slideWidth = widthPerSlide;
}
/**
* Define the slide container width
* Make non visible gaps of non visible cards scrollable and is used to compute the maxScrollableContent (strechingEffect)
*/
setWidthSlideContainer() {
this.widthSlideContainer =
this.selectSlides().length * this.slideWidthWithGap - this.gap;
this.slidesContainer.style.width = `${this.widthSlideContainer}px`;
}
selectSlides() {
return this.carousel.querySelectorAll('.carousel-slide');
}
slidesToArray() {
return Array.from(this.slides);
}
selectSlidesContainer() {
return this.carousel.querySelector('.slides-container');
}
/**
* Set number of dots
* If infinite mode, one more window than normal mode.
*/
setNumberDots() {
if (this.loop)
return this.totalSlides;
return this.slideToShow > 1
? this.totalSlides - this.slideToShow + 1
: this.totalSlides;
}
/**
* Get the max scrollable content
* Useful for the streching effect (not infinite mode), end of the slides
*/
getMaxScroll() {
return (this.numberDots() - 1) * this.slideWidthWithGap;
}
setDraggableImgToFalse() {
const images = this.slidesContainer.querySelectorAll('img');
images?.forEach((image) => {
image.setAttribute('draggable', 'false');
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jYXJvdXNlbC9zcmMvbGliL2Nhcm91c2VsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFdkMsTUFBTSxPQUFPLFFBQVE7SUFpQm5CLFlBQ21CLFFBQXdCLEVBQ3hCLGdCQUFvQyxFQUM5QyxXQUFtQixFQUNuQixVQUFrQixFQUNULGFBQXFCLEVBQ3JCLEdBQVcsRUFDVixVQUFtQixFQUNuQixJQUFhO1FBUGIsYUFBUSxHQUFSLFFBQVEsQ0FBZ0I7UUFDeEIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFvQjtRQUM5QyxnQkFBVyxHQUFYLFdBQVcsQ0FBUTtRQUNuQixlQUFVLEdBQVYsVUFBVSxDQUFRO1FBQ1Qsa0JBQWEsR0FBYixhQUFhLENBQVE7UUFDckIsUUFBRyxHQUFILEdBQUcsQ0FBUTtRQUNWLGVBQVUsR0FBVixVQUFVLENBQVM7UUFDbkIsU0FBSSxHQUFKLElBQUksQ0FBUztRQXBCaEMsZUFBVSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2Qix5QkFBb0IsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakMsb0JBQWUsR0FBRyxNQUFNLENBQVcsRUFBRSxDQUFDLENBQUM7UUFHdkMsZ0JBQVcsR0FBRyxDQUFDLENBQUM7UUFDaEIsdUJBQWtCLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZCLG9CQUFlLEdBQUcsQ0FBQyxDQUFDO1FBR3BCLGtCQUFhLEdBQXFCLEVBQUUsQ0FBQztRQVluQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN2QixDQUFDO0lBRUQsSUFBSTtRQUNGLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixF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QUFtQixDQUFtQixDQUFDO0lBQzVFLENBQUM7SUFFRDs7O09BR0c7SUFDSCxhQUFhO1FBQ1gsSUFBSSxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUV2QyxPQUFPLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQztZQUN6QixDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUM7WUFDekMsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDdkIsQ0FBQztJQUVEOzs7T0FHRztJQUNILFlBQVk7UUFDVixPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztJQUMxRCxDQUFDO0lBRUQsc0JBQXNCO1FBQ3BCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUQsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ3hCLEtBQUssQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzNDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5leHBvcnQgY2xhc3MgQ2Fyb3VzZWwge1xyXG4gIHNsaWRlcyE6IE5vZGVMaXN0T2Y8SFRNTERpdkVsZW1lbnQ+O1xyXG4gIG9yaWdpbmFsU2xpZGVXaWR0aCE6IG51bWJlcjtcclxuICBzbGlkZVdpZHRoV2l0aEdhcCE6IG51bWJlcjtcclxuXHJcbiAgbnVtYmVyRG90cyA9IHNpZ25hbCgwKTtcclxuICBtYXhTY3JvbGxhYmxlQ29udGVudCA9IHNpZ25hbCgwKTtcclxuICBhcnJheU51bWJlckRvdHMgPSBzaWduYWw8bnVtYmVyW10+KFtdKTtcclxuXHJcbiAgc2xpZGVzQ29udGFpbmVyITogSFRNTERpdkVsZW1lbnQ7XHJcbiAgdG90YWxTbGlkZXMgPSAwO1xyXG4gIGluaXRpYWxTbGlkZVRvU2hvdyA9IDE7XHJcbiAgcGFkZGluZ0Nhcm91c2VsID0gMDtcclxuICBjYXJvdXNlbFdpZHRoITogbnVtYmVyO1xyXG4gIHdpZHRoU2xpZGVDb250YWluZXIhOiBudW1iZXI7XHJcbiAgYXJyYXlPZlNsaWRlczogSFRNTERpdkVsZW1lbnRbXSA9IFtdO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgY2Fyb3VzZWw6IEhUTUxEaXZFbGVtZW50LFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBtYXhXaWR0aENhcm91c2VsOiBudW1iZXIgfCB1bmRlZmluZWQsXHJcbiAgICBwdWJsaWMgc2xpZGVUb1Nob3c6IG51bWJlcixcclxuICAgIHB1YmxpYyBzbGlkZVdpZHRoOiBudW1iZXIsXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgc2xpZGVNYXhXaWR0aDogbnVtYmVyLFxyXG4gICAgcHVibGljIHJlYWRvbmx5IGdhcDogbnVtYmVyLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSByZXNwb25zaXZlOiBib29sZWFuLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBsb29wOiBib29sZWFuXHJcbiAgKSB7XHJcbiAgICB0aGlzLmluaXQoKTtcclxuICB9XHJcblxyXG4gIGdldCBjYXJvdXNlbEVsZW1lbnQoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5jYXJvdXNlbDtcclxuICB9XHJcblxyXG4gIGluaXQoKSB7XHJcbiAgICB0aGlzLnBhZGRpbmdDYXJvdXNlbCA9IHRoaXMuZ2V0UGFkZGluZ0Nhcm91c2VsKCk7XHJcbiAgICB0aGlzLmluaXRpYWxTbGlkZVRvU2hvdyA9IHRoaXMuc2xpZGVUb1Nob3c7XHJcbiAgICB0aGlzLnNsaWRlc0NvbnRhaW5lciA9IHRoaXMuc2VsZWN0U2xpZGVzQ29udGFpbmVyKCk7XHJcbiAgICB0aGlzLnNsaWRlcyA9IHRoaXMuc2VsZWN0U2xpZGVzKCk7XHJcbiAgICB0aGlzLmFycmF5T2ZTbGlkZXMgPSB0aGlzLnNsaWRlc1RvQXJyYXkoKTtcclxuICAgIHRoaXMudG90YWxTbGlkZXMgPSB0aGlzLnNsaWRlcy5sZW5ndGg7XHJcbiAgICB0aGlzLm9yaWdpbmFsU2xpZGVXaWR0aCA9IHRoaXMuc2xpZGVXaWR0aDtcclxuICAgIHRoaXMuc2V0V2lkdGhTbGlkZXMoKTtcclxuICAgIHRoaXMuc2V0TWF4V2lkdGhDYXJvdXNlbCgpO1xyXG4gICAgdGhpcy51cGRhdGVQcm9wZXJ0aWVzKCk7XHJcbiAgICB0aGlzLnNsaWRlc0NvbnRhaW5lci5zdHlsZS5nYXAgPSBgJHt0aGlzLmdhcH1weGA7XHJcbiAgICB0aGlzLnNldERyYWdnYWJsZUltZ1RvRmFsc2UoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgc2xpZGUgd2lkdGggYW5kIG1heCB3aWR0aFxyXG4gICAqIE5COiBJbiByZXNwb25zaXZlIG1vZGUsIHdpZHRoIGlzIGF1dG9tYXRpY2FsbHkgYWRhcHRlZCB0aHJvdWdoIHRoZSBzZXRBdXRvQ29sdW1uU2xpZGVDb250YWluZXIoKSBtZXRob2QuXHJcbiAgICpcclxuICAgKi9cclxuICBzZXRXaWR0aFNsaWRlcygpIHtcclxuICAgIGZvciAoY29uc3Qgc2xpZGUgb2YgdGhpcy5zbGlkZXMpIHtcclxuICAgICAgc2xpZGUuc3R5bGUubWF4V2lkdGggPSBgJHt0aGlzLnNsaWRlTWF4V2lkdGh9cHhgO1xyXG4gICAgICBzbGlkZS5zdHlsZS53aWR0aCA9ICcxMDAlJztcclxuICAgICAgc2xpZGUuc3R5bGUudXNlclNlbGVjdCA9ICdub25lJztcclxuXHJcbiAgICAgIGlmICghdGhpcy5yZXNwb25zaXZlKSB7XHJcbiAgICAgICAgc2xpZGUuc3R5bGUud2lkdGggPSBgJHt0aGlzLnNsaWRlV2lkdGh9cHhgO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGUgY2Fyb3VzZWwgcHJvcGVydGllc1xyXG4gICAqIE9jY3VycyBhdCBzdGFydCBhbmQgYXQgcmVzaXppbmcuXHJcbiAgICovXHJcbiAgdXBkYXRlUHJvcGVydGllcygpIHtcclxuICAgIHRoaXMuY2Fyb3VzZWxXaWR0aCA9IHRoaXMuY2Fyb3VzZWwuY2xpZW50V2lkdGg7XHJcbiAgICBpZiAodGhpcy5yZXNwb25zaXZlKSB7XHJcbiAgICAgIHRoaXMudXBkYXRlU2xpZGVUb1Nob3dSZXNwb25zaXZlKCk7XHJcbiAgICAgIHRoaXMuc2V0QXV0b0NvbHVtblNsaWRlQ29udGFpbmVyKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnVwZGF0ZVNsaWRlVG9TaG93Tm90UmVzcG9uc2l2ZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMubnVtYmVyRG90cy5zZXQodGhpcy5zZXROdW1iZXJEb3RzKCkpO1xyXG4gICAgdGhpcy5hcnJheU51bWJlckRvdHMuc2V0KFsuLi5BcnJheSh0aGlzLm51bWJlckRvdHMoKSkua2V5cygpXSk7XHJcblxyXG4gICAgdGhpcy5zbGlkZVdpZHRoV2l0aEdhcCA9IHRoaXMuc2xpZGVXaWR0aCArIHRoaXMuZ2FwO1xyXG4gICAgdGhpcy5zZXRXaWR0aFNsaWRlQ29udGFpbmVyKCk7XHJcbiAgICB0aGlzLm1heFNjcm9sbGFibGVDb250ZW50LnNldCh0aGlzLmdldE1heFNjcm9sbCgpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFVwZGF0ZSBzbGlkZSB0byBzaG93IChyZXNwb25zaXZlIG1vZGUpXHJcbiAgICogQ29tcHV0ZXMgdGhlIG51bWJlciBvZiBzbGlkZSBmaXR0aW5nXHJcbiAgICovXHJcbiAgdXBkYXRlU2xpZGVUb1Nob3dSZXNwb25zaXZlKCkge1xyXG4gICAgY29uc3Qgc2xpZGVXaWR0aFBsdXNHYXAgPSB0aGlzLm9yaWdpbmFsU2xpZGVXaWR0aCArIHRoaXMuZ2FwO1xyXG5cclxuICAgIGNvbnN0IHJlZmVyZW5jZVdpZHRoID0gTWF0aC5taW4oXHJcbiAgICAgIHRoaXMuY2Fyb3VzZWxXaWR0aCxcclxuICAgICAgdGhpcy5tYXhXaWR0aENhcm91c2VsIHx8IEluZmluaXR5LFxyXG4gICAgICB3aW5kb3cuaW5uZXJXaWR0aFxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBzbGlkZUZpdHRpbmcgPSBNYXRoLmZsb29yKHJlZmVyZW5jZVdpZHRoIC8gc2xpZGVXaWR0aFBsdXNHYXApIHx8IDE7XHJcblxyXG4gICAgdGhpcy5kZXRlcm1pbmVTbGlkZVRvU2hvdyhzbGlkZUZpdHRpbmcpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGV0ZXJtaW5lIHNsaWRlIHRvIHNob3dcclxuICAgKiBVc2VmdWwgdG8gY29tcHV0ZSB0aGUgc2xpZGUgZGlzcGxheWVkIG9uIHNjcmVlbiBhbmQgZm9yIHRoZSBzbGlkZXIgY2xhc3MuXHJcbiAgICogSW4gbm90IHJlc3BvbnNpdmUgbW9kZSwgdGhlIG1heGltdW0gc2xpZGVzIHRvIHNob3cgaXMgZGV0ZXJtaW5lZCBieSB0aGUgbWF4aW11bSBhdmFpbGFibGUgc3BhY2UgYW5kIHRoZSB3aWR0aCBvZiB0aGUgc2xpZGUgc2V0IGJ5IHRoZSB1c2VyLlxyXG4gICAqL1xyXG4gIGRldGVybWluZVNsaWRlVG9TaG93KHNsaWRlRml0dGluZzogbnVtYmVyKSB7XHJcbiAgICBjb25zdCBtYXhTbGlkZXNUb1Nob3cgPSB0aGlzLnJlc3BvbnNpdmVcclxuICAgICAgPyB0aGlzLmluaXRpYWxTbGlkZVRvU2hvd1xyXG4gICAgICA6IHRoaXMudG90YWxTbGlkZXM7XHJcblxyXG4gICAgdGhpcy5zbGlkZVRvU2hvdyA9IE1hdGgubWluKHNsaWRlRml0dGluZywgbWF4U2xpZGVzVG9TaG93KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFVwZGF0ZSBzbGlkZSB0byBzaG93IChub3QgcmVzcG9uc2l2ZSBtb2RlKVxyXG4gICAqIENvbXB1dGVzIHRoZSBudW1iZXIgb2Ygc2xpZGUgZml0dGluZy4gVGhlIG51bWJlciBvZiBzbGlkZXMgdG8gYmUgc2hvd24gYXJlIGRldGVybWluZWQgYnkgdGhlIG51bWJlciBvZiBzbGlkZXMgZml0dGluZyB3aXRoaW4gaXRzIGNvbnRhaW5lci5cclxuICAgKi9cclxuICB1cGRhdGVTbGlkZVRvU2hvd05vdFJlc3BvbnNpdmUoKSB7XHJcbiAgICBjb25zdCBzbGlkZVdpZHRoUGx1c0dhcCA9IHRoaXMuc2xpZGVXaWR0aCArIHRoaXMuZ2FwO1xyXG5cclxuICAgIGNvbnN0IHJlZmVyZW5jZVdpZHRoID0gTWF0aC5taW4oXHJcbiAgICAgIHRoaXMuY2Fyb3VzZWxXaWR0aCxcclxuICAgICAgdGhpcy5tYXhXaWR0aENhcm91c2VsIHx8IEluZmluaXR5LFxyXG4gICAgICB3aW5kb3cuaW5uZXJXaWR0aFxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBudW1iZXJPZlNsaWRlc0NvbXB1dGVkID1cclxuICAgICAgTWF0aC5mbG9vcihyZWZlcmVuY2VXaWR0aCAvIHNsaWRlV2lkdGhQbHVzR2FwKSB8fCAxO1xyXG4gICAgY29uc3Qgc2xpZGVGaXR0aW5nID0gTWF0aC5taW4obnVtYmVyT2ZTbGlkZXNDb21wdXRlZCwgdGhpcy50b3RhbFNsaWRlcyk7XHJcblxyXG4gICAgdGhpcy5kZXRlcm1pbmVTbGlkZVRvU2hvdyhzbGlkZUZpdHRpbmcpO1xyXG4gIH1cclxuXHJcbiAgZ2V0UGFkZGluZ0Nhcm91c2VsKCkge1xyXG4gICAgY29uc3QgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRoaXMuY2Fyb3VzZWwpO1xyXG4gICAgY29uc3QgcGFkZGluZ0xlZnQgPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ3BhZGRpbmctbGVmdCcpO1xyXG4gICAgY29uc3QgcGFkZGluZ1JpZ2h0ID0gY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCdwYWRkaW5nLXJpZ2h0Jyk7XHJcblxyXG4gICAgcmV0dXJuIHBhcnNlRmxvYXQocGFkZGluZ0xlZnQpICsgcGFyc2VGbG9hdChwYWRkaW5nUmlnaHQpO1xyXG4gIH1cclxuXHJcbiAgc2V0TWF4V2lkdGhDYXJvdXNlbCgpIHtcclxuICAgIHRoaXMuY2Fyb3VzZWwuc3R5bGUubWF4V2lkdGggPSBgJHt0aGlzLm1heFdpZHRoQ2Fyb3VzZWx9cHhgO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0IHRoZSB3aXRoIG9mIGEgc2xpZGUsIHJlc3BvbnNpdmUgbW9kZVxyXG4gICAqIFRoZXJlIGFyZSBbbiBjYXJkcyAtIDFdIGdhcHMgKDMgY2FyZHMsIDIgZ2FwcylcclxuICAgKi9cclxuICBzZXRBdXRvQ29sdW1uU2xpZGVDb250YWluZXIoKSB7XHJcbiAgICBjb25zdCB3aW5kb3dXaWR0aCA9XHJcbiAgICAgIHRoaXMuY2Fyb3VzZWxXaWR0aCAtXHJcbiAgICAgIHRoaXMucGFkZGluZ0Nhcm91c2VsIC1cclxuICAgICAgKHRoaXMuc2xpZGVUb1Nob3cgLSAxKSAqIHRoaXMuZ2FwO1xyXG5cclxuICAgIGNvbnN0IHdpZHRoUGVyU2xpZGUgPSB3aW5kb3dXaWR0aCAvIHRoaXMuc2xpZGVUb1Nob3c7XHJcbiAgICB0aGlzLnNsaWRlc0NvbnRhaW5lci5zdHlsZS5ncmlkQXV0b0NvbHVtbnMgPSBgJHt3aWR0aFBlclNsaWRlfXB4YDtcclxuXHJcbiAgICB0aGlzLnNsaWRlV2lkdGggPSB3aWR0aFBlclNsaWRlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGVmaW5lIHRoZSBzbGlkZSBjb250YWluZXIgd2lkdGhcclxuICAgKiBNYWtlIG5vbiB2aXNpYmxlIGdhcHMgb2Ygbm9uIHZpc2libGUgY2FyZHMgc2Nyb2xsYWJsZSBhbmQgaXMgdXNlZCB0byBjb21wdXRlIHRoZSBtYXhTY3JvbGxhYmxlQ29udGVudCAoc3RyZWNoaW5nRWZmZWN0KVxyXG4gICAqL1xyXG4gIHNldFdpZHRoU2xpZGVDb250YWluZXIoKSB7XHJcbiAgICB0aGlzLndpZHRoU2xpZGVDb250YWluZXIgPVxyXG4gICAgICB0aGlzLnNlbGVjdFNsaWRlcygpLmxlbmd0aCAqIHRoaXMuc2xpZGVXaWR0aFdpdGhHYXAgLSB0aGlzLmdhcDtcclxuICAgIHRoaXMuc2xpZGVzQ29udGFpbmVyLnN0eWxlLndpZHRoID0gYCR7dGhpcy53aWR0aFNsaWRlQ29udGFpbmVyfXB4YDtcclxuICB9XHJcblxyXG4gIHNlbGVjdFNsaWRlcygpOiBOb2RlTGlzdE9mPEhUTUxEaXZFbGVtZW50PiB7XHJcbiAgICByZXR1cm4gdGhpcy5jYXJvdXNlbC5xdWVyeVNlbGVjdG9yQWxsKCcuY2Fyb3VzZWwtc2xpZGUnKTtcclxuICB9XHJcblxyXG4gIHNsaWRlc1RvQXJyYXkoKSB7XHJcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLnNsaWRlcyk7XHJcbiAgfVxyXG5cclxuICBzZWxlY3RTbGlkZXNDb250YWluZXIoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5jYXJvdXNlbC5xdWVyeVNlbGVjdG9yKCcuc2xpZGVzLWNvbnRhaW5lcicpIGFzIEhUTUxEaXZFbGVtZW50O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0IG51bWJlciBvZiBkb3RzXHJcbiAgICogSWYgaW5maW5pdGUgbW9kZSwgb25lIG1vcmUgd2luZG93IHRoYW4gbm9ybWFsIG1vZGUuXHJcbiAgICovXHJcbiAgc2V0TnVtYmVyRG90cygpIHtcclxuICAgIGlmICh0aGlzLmxvb3ApIHJldHVybiB0aGlzLnRvdGFsU2xpZGVzO1xyXG5cclxuICAgIHJldHVybiB0aGlzLnNsaWRlVG9TaG93ID4gMVxyXG4gICAgICA/IHRoaXMudG90YWxTbGlkZXMgLSB0aGlzLnNsaWRlVG9TaG93ICsgMVxyXG4gICAgICA6IHRoaXMudG90YWxTbGlkZXM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgdGhlIG1heCBzY3JvbGxhYmxlIGNvbnRlbnRcclxuICAgKiBVc2VmdWwgZm9yIHRoZSBzdHJlY2hpbmcgZWZmZWN0IChub3QgaW5maW5pdGUgbW9kZSksIGVuZCBvZiB0aGUgc2xpZGVzXHJcbiAgICovXHJcbiAgZ2V0TWF4U2Nyb2xsKCkge1xyXG4gICAgcmV0dXJuICh0aGlzLm51bWJlckRvdHMoKSAtIDEpICogdGhpcy5zbGlkZVdpZHRoV2l0aEdhcDtcclxuICB9XHJcblxyXG4gIHNldERyYWdnYWJsZUltZ1RvRmFsc2UoKSB7XHJcbiAgICBjb25zdCBpbWFnZXMgPSB0aGlzLnNsaWRlc0NvbnRhaW5lci5xdWVyeVNlbGVjdG9yQWxsKCdpbWcnKTtcclxuICAgIGltYWdlcz8uZm9yRWFjaCgoaW1hZ2UpID0+IHtcclxuICAgICAgaW1hZ2Uuc2V0QXR0cmlidXRlKCdkcmFnZ2FibGUnLCAnZmFsc2UnKTtcclxuICAgIH0pO1xyXG4gIH1cclxufVxyXG4iXX0=