import { Injectable } from '@angular/core'; import { Observable, fromEvent, Subscription, pipe, from, Subject } from 'rxjs'; import { filter, map, startWith, distinctUntilChanged } from 'rxjs/operators'; import { EsbImageSliderConfig } from '../esb-image-slider-config'; @Injectable() export class EsbImageSliderService { private imageLoadedCount = 0; private imageLoad: Subject; private config: EsbImageSliderConfig; private minWidthBreakpoint: number; constructor() { } public init(imageSources: string[], config: EsbImageSliderConfig) { this.imageLoadedCount = 0; this.imageLoad = new Subject(); config.autoplayDelay = config.autoplayDelay < 1000 ? 1000 : config.autoplayDelay; this.config = config; this.loadImages(imageSources); } public onImageLoad(): Observable { return this.imageLoad.asObservable(); } public getConfig(): EsbImageSliderConfig { return Object.assign({}, this.config); } private loadImages(imageSources: string[]): void { const createImageElement = (image: string): void => { const imgElement = document.createElement('img'); imgElement.src = image; imgElement.onload = this.onImageElementLoad.bind(this, imageSources, image); imgElement.onerror = this.onImageElementLoadError.bind(this, imageSources, image); }; imageSources.forEach(createImageElement); } private onImageElementLoad(imageSources: string[], image: string): any { this.imageLoadedCount++; this.imageLoad.next(image); this.carouselTinyLogger(image, true); this.emitIfAllImagesLoaded(imageSources); } private onImageElementLoadError(imageSources: string[], image: string): any { imageSources.splice(imageSources.indexOf(image), 1); this.carouselTinyLogger(image, false); this.emitIfAllImagesLoaded(imageSources); } private emitIfAllImagesLoaded(imageSources: string[]) { if (this.imageLoadedCount === imageSources.length) { this.imageLoad.complete(); } } private carouselTinyLogger(image: string, isLoaded: boolean): void { if (isLoaded) { return; } console.error(`EsbImageSliderService: image load error: ${image}`); } public onResize(minWidthBreakpoint: number, scrollBar?: boolean): Observable { this.minWidthBreakpoint = minWidthBreakpoint; return fromEvent(window, 'resize').pipe( map(() => this.assertSize(scrollBar)), startWith(this.assertSize(scrollBar)), distinctUntilChanged() ); }; private assertSize(scrollBar?: boolean): boolean { const area = scrollBar ? window.innerWidth : document.documentElement.clientWidth; return this.minWidthBreakpoint <= area; } }