UNPKG

@paperbits/core

Version:
155 lines (127 loc) 5.67 kB
import { coerce } from "@paperbits/common"; import { Events } from "@paperbits/common/events"; export class CarouselHTMLElement extends HTMLElement { private currentSlideIndex: number; private autoplay: boolean; private pauseOnHover: boolean; private autoplayInterval: number; private autoplayHandler: any; constructor() { super(); const activeSlideAttr = this.getAttribute("data-active-slide"); const autoplayAttr = this.getAttribute("data-carousel-autoplay"); const pauseOnHoverAttr = this.getAttribute("data-carousel-pauseonhover"); const autoplayIntervalAttr = this.getAttribute("data-carousel-autoplay-interval"); this.currentSlideIndex = !!activeSlideAttr ? parseInt(activeSlideAttr) : 0; this.autoplay = autoplayAttr === "true"; this.pauseOnHover = pauseOnHoverAttr === "true"; this.autoplayInterval = autoplayIntervalAttr ? parseInt(autoplayIntervalAttr) : 5000; } static get observedAttributes(): string[] { return ["data-active-slide", "data-carousel-autoplay", "data-carousel-autoplay-interval", "data-carousel-pauseonhover"]; } public attributeChangedCallback(name: string, oldValue: string, newValue: string): void { if (name !== "data-active-slide" && name !== "data-carousel-autoplay" && name !== "data-carousel-autoplay-interval" && name !== "data-carousel-pauseonhover") { return; } if ((!newValue && name !== "data-carousel-autoplay") || oldValue === newValue) { return; } switch (name) { case "data-carousel-autoplay-interval": this.autoplayInterval = parseInt(newValue); if (this.autoplay) { this.disableAutoplay(); this.enableAutoplay(); } break; case "data-carousel-autoplay": this.autoplay = newValue === "true"; this.autoplay ? this.enableAutoplay() : this.disableAutoplay(); break; case "data-active-slide": this.currentSlideIndex = parseInt(newValue); this.setActiveItem(this.currentSlideIndex); break; case "data-carousel-pauseonhover": this.pauseOnHover = newValue === "true"; this.pauseOnHover ? this.enablePauseOnHover() : this.disablePauseOnHover(); break; default: break; } } private setActiveItem = (index: number) => { this.style.setProperty("--slide", index.toString()); const activeIndicator = this.querySelector(".carousel-indicator.active"); if (activeIndicator) { activeIndicator.classList.remove("active"); } setImmediate(() => { const carouselIndicators = coerce<HTMLDListElement>(this.querySelectorAll(".carousel-indicator")); if (carouselIndicators && carouselIndicators.length > 0) { carouselIndicators[index]?.classList.add("active"); } }); }; private enableAutoplay = (): void => { this.disableAutoplay(); this.autoplayHandler = setInterval(() => { this.nextSlide(); }, this.autoplayInterval); } private disableAutoplay = (): void => { clearInterval(this.autoplayHandler); } private enablePauseOnHover = (): void => { if (this.autoplay) { const element = <HTMLElement>this; element.addEventListener(Events.MouseOver, this.disableAutoplay); element.addEventListener(Events.MouseOut, this.enableAutoplay); } } private disablePauseOnHover = (): void => { const element = <HTMLElement>this; element.removeEventListener(Events.MouseOver, this.disableAutoplay); element.removeEventListener(Events.MouseOut, this.enableAutoplay); } private nextSlide = (): void => { const element = <HTMLElement>this; const carouselItems = coerce<Element>(element.querySelectorAll(".carousel-item")); this.currentSlideIndex++; if (this.currentSlideIndex >= carouselItems.length) { this.currentSlideIndex = 0; } this.setActiveItem(this.currentSlideIndex); } private prevSlide = (): void => { const element = <HTMLElement>this; const carouselItems = coerce<Element>(element.querySelectorAll(".carousel-item")); this.currentSlideIndex--; if (this.currentSlideIndex < 0) { this.currentSlideIndex = carouselItems.length - 1; } this.setActiveItem(this.currentSlideIndex); } public connectedCallback(): void { const element = <HTMLElement>this; element.addEventListener(Events.Click, oEvent => { const clickElement = oEvent.composedPath()[0] as HTMLElement; const prevButton = clickElement.closest(".carousel-control-prev") ? true : false; const nextButton = clickElement.closest(".carousel-control-next") ? true : false; if (prevButton) { this.prevSlide(); } else if (nextButton) { this.nextSlide(); } }); if (this.enablePauseOnHover) { this.enablePauseOnHover(); } if (this.autoplay) { this.enableAutoplay(); } } }