/** * CarouselCardTrackingClient * @description Track the Carousel card component * @param {HTMLElement} mountElement - The Carousel card component */ class CarouselCardTrackingClient { component: HTMLElement position: number total: number private intersectionObserver: IntersectionObserver id: string | undefined constructor({ component, index, total, }: { component: HTMLElement index: number total: number }) { this.component = component this.id = component.getAttribute('data-component-id') || undefined this.position = index + 1 this.total = total this.intersectionObserver = new IntersectionObserver( this.onChange.bind(this), // adjust right margin to prevent triggering when the next card is partially in view before scrolling horizontally // adjust bottom margin to trigger event before card is fully in vertical view { rootMargin: `0px -212px -300px 0px`, threshold: 0, } ) this.intersectionObserver.observe(this.component) this.destroy = this.destroy.bind(this) this.component.dataset.initialised = 'true' } onChange(changes: IntersectionObserverEntry[]): void { changes.forEach((change) => { if (change.target !== this.component) { return } if ( change.boundingClientRect.height > 0 && (change.isIntersecting || change.intersectionRatio >= 1) ) { const event = new CustomEvent('oTracking.event', { detail: { category: 'component', action: 'view', trigger_action: 'enter-viewport', url: window.location.href, component: { id: this.id, name: 'cp-carousel-card', position: this.position, }, custom: [ { name: 'total-cards', value: this.total, }, ], }, bubbles: true, }) document.body.dispatchEvent(event) this.destroy() } }) } static init(rootElement: HTMLElement): CarouselCardTrackingClient[] { if (!rootElement) return [] return Array.from( rootElement.querySelectorAll( '[data-component="carousel-card"]:not([data-initialised])' ) ).map( (el, index, all) => new CarouselCardTrackingClient({ component: el, index, total: all.length, }) ) } destroy(): void { if (!this.component) return this.intersectionObserver?.unobserve(this.component) this.intersectionObserver?.disconnect() this.component.removeAttribute('data-initialised') } } export { CarouselCardTrackingClient }