@rybos/ngx-gallery
Version:
A simple responsive native gallery component for Angular 15.
1 lines • 150 kB
Source Map (JSON)
{"version":3,"file":"rybos-ngx-gallery.mjs","sources":["../../../projects/gallery/src/lib/ngx-gallery.service.ts","../../../projects/gallery/src/lib/ngx-gallery-arrows/ngx-gallery-arrows.component.ts","../../../projects/gallery/src/lib/ngx-gallery-arrows/ngx-gallery-arrows.component.html","../../../projects/gallery/src/lib/ngx-gallery-action/ngx-gallery-action.component.ts","../../../projects/gallery/src/lib/ngx-gallery-action/ngx-gallery-action.component.html","../../../projects/gallery/src/lib/ngx-gallery-bullets/ngx-gallery-bullets.component.ts","../../../projects/gallery/src/lib/ngx-gallery-bullets/ngx-gallery-bullets.component.html","../../../projects/gallery/src/lib/ngx-gallery-preview/ngx-gallery-preview.component.ts","../../../projects/gallery/src/lib/ngx-gallery-preview/ngx-gallery-preview.component.html","../../../projects/gallery/src/lib/ngx-gallery-animation.ts","../../../projects/gallery/src/lib/ngx-gallery-image/ngx-gallery-image.component.ts","../../../projects/gallery/src/lib/ngx-gallery-image/ngx-gallery-image.component.html","../../../projects/gallery/src/lib/ngx-gallery-order.ts","../../../projects/gallery/src/lib/ngx-gallery-thumbnails/ngx-gallery-thumbnails.component.ts","../../../projects/gallery/src/lib/ngx-gallery-thumbnails/ngx-gallery-thumbnails.component.html","../../../projects/gallery/src/lib/ngx-gallery-action.ts","../../../projects/gallery/src/lib/ngx-gallery-layout.ts","../../../projects/gallery/src/lib/ngx-gallery-image-size.ts","../../../projects/gallery/src/lib/ngx-gallery-options.ts","../../../projects/gallery/src/lib/ngx-gallery-ordered-image.ts","../../../projects/gallery/src/lib/ngx-gallery.component.ts","../../../projects/gallery/src/lib/ngx-gallery.component.html","../../../projects/gallery/src/lib/ngx-gallery.module.ts","../../../projects/gallery/src/lib/ngx-gallery-image.ts","../../../projects/gallery/src/public-api.ts","../../../projects/gallery/src/rybos-ngx-gallery.ts"],"sourcesContent":["import {ElementRef, Injectable, Renderer2} from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class NgxGalleryService {\r\n private swipeHandlers: Map<string, (() => void)[]> = new Map<string, (() => void)[]>();\r\n\r\n constructor(private renderer: Renderer2) {\r\n }\r\n\r\n manageSwipe(status: boolean, element: ElementRef, id: string, nextHandler: () => void, prevHandler: () => void): void {\r\n\r\n const handlers = this.getSwipeHandlers(id);\r\n\r\n // swipeleft and swiperight are available only if hammerjs is included\r\n try {\r\n if (status && !handlers) {\r\n this.swipeHandlers.set(id, [\r\n this.renderer.listen(element.nativeElement, 'swipeleft', () => nextHandler()),\r\n this.renderer.listen(element.nativeElement, 'swiperight', () => prevHandler())\r\n ]);\r\n } else if (!status && handlers) {\r\n handlers.map((handler) => handler());\r\n this.removeSwipeHandlers(id);\r\n }\r\n } catch (e) {\r\n }\r\n }\r\n\r\n validateUrl(url: string): string {\r\n if (url.replace) {\r\n return url.replace(new RegExp(' ', 'g'), '%20')\r\n .replace(new RegExp('\\'', 'g'), '%27');\r\n } else {\r\n return url;\r\n }\r\n }\r\n\r\n getBackgroundUrl(image: string) {\r\n return 'url(\\'' + this.validateUrl(image) + '\\')';\r\n }\r\n\r\n getFileType (fileSource: string): string {\r\n const fileExtension = fileSource.split('.').pop().toLowerCase();\r\n if (fileExtension === 'avi' || fileExtension === 'flv'\r\n || fileExtension === 'wmv' || fileExtension === 'mov'\r\n || fileExtension === 'mp4') {\r\n return 'video';\r\n }\r\n return 'image';\r\n}\r\n\r\n private getSwipeHandlers(id: string): (() => void)[] | undefined {\r\n return this.swipeHandlers.get(id);\r\n }\r\n\r\n private removeSwipeHandlers(id: string): void {\r\n this.swipeHandlers.delete(id);\r\n }\r\n}\r\n","import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';\r\n\r\n@Component({\r\n selector: 'ngx-gallery-arrows',\r\n templateUrl: './ngx-gallery-arrows.component.html',\r\n styleUrls: ['./ngx-gallery-arrows.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class NgxGalleryArrowsComponent {\r\n @Input() prevDisabled: boolean;\r\n @Input() nextDisabled: boolean;\r\n @Input() arrowPrevIcon: string;\r\n @Input() arrowNextIcon: string;\r\n\r\n @Output() prevClick = new EventEmitter();\r\n @Output() nextClick = new EventEmitter();\r\n\r\n constructor() { }\r\n\r\n handlePrevClick(): void {\r\n this.prevClick.emit();\r\n }\r\n\r\n handleNextClick(): void {\r\n this.nextClick.emit();\r\n }\r\n}\r\n","<div class=\"ngx-gallery-arrows-wrapper ngx-gallery-arrow-left\">\r\n <div class=\"ngx-gallery-icon ngx-gallery-arrow\" aria-hidden=\"true\" (click)=\"handlePrevClick()\" [class.ngx-gallery-disabled]=\"prevDisabled\">\r\n <i class=\"ngx-gallery-icon-content {{arrowPrevIcon}}\"></i>\r\n </div>\r\n</div>\r\n<div class=\"ngx-gallery-arrows-wrapper ngx-gallery-arrow-right\">\r\n <div class=\"ngx-gallery-icon ngx-gallery-arrow\" aria-hidden=\"true\" (click)=\"handleNextClick()\" [class.ngx-gallery-disabled]=\"nextDisabled\">\r\n <i class=\"ngx-gallery-icon-content {{arrowNextIcon}}\"></i>\r\n </div>\r\n</div>\r\n","import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';\r\n\r\n@Component({\r\n selector: 'ngx-gallery-action',\r\n templateUrl: './ngx-gallery-action.component.html',\r\n styleUrls: ['./ngx-gallery-action.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class NgxGalleryActionComponent {\r\n @Input() icon: string;\r\n @Input() disabled = false;\r\n @Input() titleText = '';\r\n\r\n @Output() closeClick: EventEmitter<Event> = new EventEmitter();\r\n\r\n constructor() {\r\n }\r\n\r\n handleClick(event: Event) {\r\n if (!this.disabled) {\r\n this.closeClick.emit(event);\r\n }\r\n\r\n event.stopPropagation();\r\n event.preventDefault();\r\n }\r\n}\r\n","<div class=\"ngx-gallery-icon\" [class.ngx-gallery-icon-disabled]=\"disabled\"\r\n aria-hidden=\"true\"\r\n title=\"{{ titleText }}\"\r\n (click)=\"handleClick($event)\">\r\n <i class=\"ngx-gallery-icon-content {{ icon }}\"></i>\r\n</div>\r\n","import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';\r\n\r\n@Component({\r\n selector: 'ngx-gallery-bullets',\r\n templateUrl: './ngx-gallery-bullets.component.html',\r\n styleUrls: ['./ngx-gallery-bullets.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class NgxGalleryBulletsComponent {\r\n @Input() count: number;\r\n @Input() active = 0;\r\n\r\n @Output() bulletChange = new EventEmitter();\r\n\r\n constructor() { }\r\n\r\n getBullets(): number[] {\r\n return Array(this.count);\r\n }\r\n\r\n handleChange(event: Event, index: number): void {\r\n this.bulletChange.emit(index);\r\n }\r\n}\r\n","<div class=\"ngx-gallery-bullet\" *ngFor=\"let bullet of getBullets(); let i = index;\" (click)=\"handleChange($event, i)\"\r\n [ngClass]=\"{ 'ngx-gallery-active': i === active }\"></div>\r\n","import {\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n HostListener,\r\n Input,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Output,\r\n Renderer2,\r\n SimpleChanges,\r\n ViewChild\r\n} from '@angular/core';\r\nimport {DomSanitizer, SafeResourceUrl, SafeStyle, SafeUrl} from '@angular/platform-browser';\r\nimport {NgxGalleryService} from '../ngx-gallery.service';\r\nimport {NgxGalleryAction} from '../ngx-gallery-action';\r\n\r\n\r\n@Component({\r\n selector: 'ngx-gallery-preview',\r\n templateUrl: './ngx-gallery-preview.component.html',\r\n styleUrls: ['./ngx-gallery-preview.component.scss'],\r\n // encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class NgxGalleryPreviewComponent implements OnInit, OnDestroy, OnChanges {\r\n src: SafeUrl;\r\n srcIndex: number;\r\n description: string;\r\n type: string;\r\n showSpinner = false;\r\n positionLeft = 0;\r\n positionTop = 0;\r\n zoomValue = 1;\r\n loading = false;\r\n rotateValue = 0;\r\n index = 0;\r\n\r\n @Input() images: string[] | SafeResourceUrl[];\r\n @Input() descriptions: string[];\r\n @Input() showDescription: boolean;\r\n @Input() arrows: boolean;\r\n @Input() arrowsAutoHide: boolean;\r\n @Input() swipe: boolean;\r\n @Input() fullscreen: boolean;\r\n @Input() forceFullscreen: boolean;\r\n @Input() closeOnClick: boolean;\r\n @Input() closeOnEsc: boolean;\r\n @Input() keyboardNavigation: boolean;\r\n @Input() arrowPrevIcon: string;\r\n @Input() arrowNextIcon: string;\r\n @Input() closeIcon: string;\r\n @Input() fullscreenIcon: string;\r\n @Input() spinnerIcon: string;\r\n @Input() autoPlay: boolean;\r\n @Input() autoPlayInterval: number;\r\n @Input() autoPlayPauseOnHover: boolean;\r\n @Input() infinityMove: boolean;\r\n @Input() zoom: boolean;\r\n @Input() zoomStep: number;\r\n @Input() zoomMax: number;\r\n @Input() zoomMin: number;\r\n @Input() zoomInIcon: string;\r\n @Input() zoomOutIcon: string;\r\n @Input() animation: boolean;\r\n @Input() actions: NgxGalleryAction[];\r\n @Input() rotate: boolean;\r\n @Input() rotateLeftIcon: string;\r\n @Input() rotateRightIcon: string;\r\n @Input() download: boolean;\r\n @Input() downloadIcon: string;\r\n @Input() bullets: boolean;\r\n\r\n @Output() previewOpen = new EventEmitter();\r\n @Output() previewClose = new EventEmitter();\r\n @Output() activeChange = new EventEmitter<number>();\r\n\r\n @ViewChild('previewImage') previewImage: any;\r\n\r\n private isOpen = false;\r\n private timer;\r\n private initialX = 0;\r\n private initialY = 0;\r\n private initialLeft = 0;\r\n private initialTop = 0;\r\n private isMove = false;\r\n\r\n private keyDownListener: () => void;\r\n\r\n constructor(private sanitization: DomSanitizer, private elementRef: ElementRef,\r\n private helperService: NgxGalleryService, private renderer: Renderer2,\r\n private changeDetectorRef: ChangeDetectorRef) {\r\n }\r\n\r\n ngOnInit() {\r\n if (this.arrows && this.arrowsAutoHide) {\r\n this.arrows = false;\r\n }\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['swipe']) {\r\n this.helperService.manageSwipe(this.swipe, this.elementRef,\r\n 'preview', () => this.showNext(), () => this.showPrev());\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.keyDownListener) {\r\n this.keyDownListener();\r\n }\r\n }\r\n\r\n @HostListener('mouseenter') onMouseEnter() {\r\n if (this.arrowsAutoHide && !this.arrows) {\r\n this.arrows = true;\r\n }\r\n }\r\n\r\n @HostListener('mouseleave') onMouseLeave() {\r\n if (this.arrowsAutoHide && this.arrows) {\r\n this.arrows = false;\r\n }\r\n }\r\n\r\n onKeyDown(e) {\r\n if (this.isOpen) {\r\n if (this.keyboardNavigation) {\r\n if (this.isKeyboardPrev(e)) {\r\n this.showPrev();\r\n } else if (this.isKeyboardNext(e)) {\r\n this.showNext();\r\n }\r\n }\r\n if (this.closeOnEsc && this.isKeyboardEsc(e)) {\r\n this.close();\r\n }\r\n }\r\n }\r\n\r\n open(index: number): void {\r\n this.previewOpen.emit();\r\n\r\n this.index = index;\r\n this.isOpen = true;\r\n this.show(true);\r\n\r\n if (this.forceFullscreen) {\r\n this.manageFullscreen();\r\n }\r\n\r\n this.keyDownListener = this.renderer.listen('window', 'keydown', (e) => this.onKeyDown(e));\r\n }\r\n\r\n close(): void {\r\n this.isOpen = false;\r\n const video = this.previewImage.nativeElement;\r\n if (\r\n video.currentTime > 0 &&\r\n !video.paused &&\r\n !video.ended &&\r\n video.readyState > 2\r\n ) {\r\n video.pause();\r\n }\r\n this.closeFullscreen();\r\n this.previewClose.emit();\r\n\r\n this.stopAutoPlay();\r\n\r\n if (this.keyDownListener) {\r\n this.keyDownListener();\r\n }\r\n }\r\n\r\n imageMouseEnter(): void {\r\n if (this.autoPlay && this.autoPlayPauseOnHover) {\r\n this.stopAutoPlay();\r\n }\r\n }\r\n\r\n imageMouseLeave(): void {\r\n if (this.autoPlay && this.autoPlayPauseOnHover) {\r\n this.startAutoPlay();\r\n }\r\n }\r\n\r\n startAutoPlay(): void {\r\n if (this.autoPlay) {\r\n this.stopAutoPlay();\r\n\r\n this.timer = setTimeout(() => {\r\n if (!this.showNext()) {\r\n this.index = -1;\r\n this.showNext();\r\n }\r\n }, this.autoPlayInterval);\r\n }\r\n }\r\n\r\n stopAutoPlay(): void {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n }\r\n }\r\n\r\n showAtIndex(index: number): void {\r\n this.index = index;\r\n this.show();\r\n }\r\n\r\n showNext(): boolean {\r\n if (this.canShowNext()) {\r\n this.index++;\r\n\r\n if (this.index === this.images.length) {\r\n this.index = 0;\r\n }\r\n\r\n this.show();\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n showPrev(): void {\r\n if (this.canShowPrev()) {\r\n this.index--;\r\n\r\n if (this.index < 0) {\r\n this.index = this.images.length - 1;\r\n }\r\n\r\n this.show();\r\n }\r\n }\r\n\r\n canShowNext(): boolean {\r\n if (this.loading) {\r\n return false;\r\n } else if (this.images) {\r\n return this.infinityMove || this.index < this.images.length - 1;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n canShowPrev(): boolean {\r\n if (this.loading) {\r\n return false;\r\n } else if (this.images) {\r\n return this.infinityMove || this.index > 0;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n manageFullscreen(): void {\r\n if (this.fullscreen || this.forceFullscreen) {\r\n const doc = document as any;\r\n\r\n if (!doc.fullscreenElement && !doc.mozFullScreenElement\r\n && !doc.webkitFullscreenElement && !doc.msFullscreenElement) {\r\n this.openFullscreen();\r\n } else {\r\n this.closeFullscreen();\r\n }\r\n }\r\n }\r\n\r\n getSafeUrl(image: string): SafeUrl {\r\n return this.sanitization.bypassSecurityTrustUrl(image);\r\n }\r\n\r\n getFileType(fileSource: string): string {\r\n return this.helperService.getFileType(fileSource);\r\n }\r\n\r\n zoomIn(): void {\r\n if (this.canZoomIn()) {\r\n this.zoomValue += this.zoomStep;\r\n\r\n if (this.zoomValue > this.zoomMax) {\r\n this.zoomValue = this.zoomMax;\r\n }\r\n }\r\n }\r\n\r\n zoomOut(): void {\r\n if (this.canZoomOut()) {\r\n this.zoomValue -= this.zoomStep;\r\n\r\n if (this.zoomValue < this.zoomMin) {\r\n this.zoomValue = this.zoomMin;\r\n }\r\n\r\n if (this.zoomValue <= 1) {\r\n this.resetPosition();\r\n }\r\n }\r\n }\r\n\r\n rotateLeft(): void {\r\n this.rotateValue -= 90;\r\n }\r\n\r\n rotateRight(): void {\r\n this.rotateValue += 90;\r\n }\r\n\r\n getTransform(): SafeStyle {\r\n return this.sanitization.bypassSecurityTrustStyle('scale(' + this.zoomValue + ') rotate(' + this.rotateValue + 'deg)');\r\n }\r\n\r\n canZoomIn(): boolean {\r\n return this.zoomValue < this.zoomMax;\r\n }\r\n\r\n canZoomOut(): boolean {\r\n return this.zoomValue > this.zoomMin;\r\n }\r\n\r\n canDragOnZoom() {\r\n return this.zoom && this.zoomValue > 1;\r\n }\r\n\r\n mouseDownHandler(e): void {\r\n if (this.canDragOnZoom()) {\r\n this.initialX = this.getClientX(e);\r\n this.initialY = this.getClientY(e);\r\n this.initialLeft = this.positionLeft;\r\n this.initialTop = this.positionTop;\r\n this.isMove = true;\r\n\r\n e.preventDefault();\r\n }\r\n }\r\n\r\n mouseUpHandler(e): void {\r\n this.isMove = false;\r\n }\r\n\r\n mouseMoveHandler(e) {\r\n if (this.isMove) {\r\n this.positionLeft = this.initialLeft + (this.getClientX(e) - this.initialX);\r\n this.positionTop = this.initialTop + (this.getClientY(e) - this.initialY);\r\n }\r\n }\r\n\r\n private getClientX(e): number {\r\n return e.touches && e.touches.length ? e.touches[0].clientX : e.clientX;\r\n }\r\n\r\n private getClientY(e): number {\r\n return e.touches && e.touches.length ? e.touches[0].clientY : e.clientY;\r\n }\r\n\r\n private resetPosition() {\r\n if (this.zoom) {\r\n this.positionLeft = 0;\r\n this.positionTop = 0;\r\n }\r\n }\r\n\r\n private isKeyboardNext(e): boolean {\r\n return e.keyCode === 39;\r\n }\r\n\r\n private isKeyboardPrev(e): boolean {\r\n return e.keyCode === 37;\r\n }\r\n\r\n private isKeyboardEsc(e): boolean {\r\n return e.keyCode === 27;\r\n }\r\n\r\n private openFullscreen(): void {\r\n const element = document.documentElement as any;\r\n\r\n if (element.requestFullscreen) {\r\n element.requestFullscreen();\r\n } else if (element.msRequestFullscreen) {\r\n element.msRequestFullscreen();\r\n } else if (element.mozRequestFullScreen) {\r\n element.mozRequestFullScreen();\r\n } else if (element.webkitRequestFullscreen) {\r\n element.webkitRequestFullscreen();\r\n }\r\n }\r\n\r\n private closeFullscreen(): void {\r\n if (this.isFullscreen()) {\r\n const doc = document as any;\r\n\r\n if (doc.exitFullscreen) {\r\n doc.exitFullscreen();\r\n } else if (doc.msExitFullscreen) {\r\n doc.msExitFullscreen();\r\n } else if (doc.mozCancelFullScreen) {\r\n doc.mozCancelFullScreen();\r\n } else if (doc.webkitExitFullscreen) {\r\n doc.webkitExitFullscreen();\r\n }\r\n }\r\n }\r\n\r\n private isFullscreen() {\r\n const doc = document as any;\r\n\r\n return doc.fullscreenElement || doc.webkitFullscreenElement\r\n || doc.mozFullScreenElement || doc.msFullscreenElement;\r\n }\r\n\r\n\r\n private show(first = false) {\r\n this.loading = true;\r\n this.stopAutoPlay();\r\n\r\n this.activeChange.emit(this.index);\r\n\r\n if (first || !this.animation) {\r\n this._show();\r\n } else {\r\n setTimeout(() => this._show(), 600);\r\n }\r\n }\r\n\r\n private _show() {\r\n this.zoomValue = 1;\r\n this.rotateValue = 0;\r\n this.resetPosition();\r\n\r\n this.src = this.getSafeUrl(this.images[this.index] as string);\r\n this.type = this.getFileType(this.images[this.index] as string);\r\n this.srcIndex = this.index;\r\n this.description = this.descriptions[this.index];\r\n this.changeDetectorRef.markForCheck();\r\n\r\n setTimeout(() => {\r\n if (this.isLoaded(this.previewImage.nativeElement) || this.type === 'video') {\r\n this.loading = false;\r\n this.startAutoPlay();\r\n this.changeDetectorRef.markForCheck();\r\n } else if (this.type === 'video') {\r\n\r\n }\r\n else {\r\n setTimeout(() => {\r\n if (this.loading) {\r\n this.showSpinner = true;\r\n this.changeDetectorRef.markForCheck();\r\n }\r\n });\r\n\r\n this.previewImage.nativeElement.onload = () => {\r\n this.loading = false;\r\n this.showSpinner = false;\r\n this.previewImage.nativeElement.onload = null;\r\n this.startAutoPlay();\r\n this.changeDetectorRef.markForCheck();\r\n };\r\n }\r\n });\r\n }\r\n\r\n private isLoaded(img): boolean {\r\n if (!img.complete) {\r\n return false;\r\n }\r\n\r\n return !(typeof img.naturalWidth !== 'undefined' && img.naturalWidth === 0);\r\n }\r\n\r\n}\r\n","<ngx-gallery-arrows *ngIf=\"arrows\" (prevClick)=\"showPrev()\" (nextClick)=\"showNext()\" [prevDisabled]=\"!canShowPrev()\"\r\n [nextDisabled]=\"!canShowNext()\" [arrowPrevIcon]=\"arrowPrevIcon\"\r\n [arrowNextIcon]=\"arrowNextIcon\"></ngx-gallery-arrows>\r\n<div class=\"ngx-gallery-preview-top\">\r\n <div class=\"ngx-gallery-preview-icons\">\r\n <ngx-gallery-action *ngFor=\"let action of actions\" [icon]=\"action.icon\" [disabled]=\"action.disabled\"\r\n [titleText]=\"action.titleText\" (closeClick)=\"action.onClick($event, index)\"></ngx-gallery-action>\r\n <a *ngIf=\"download && src\" [href]=\"src\" class=\"ngx-gallery-icon\" aria-hidden=\"true\" download>\r\n <i class=\"ngx-gallery-icon-content {{ downloadIcon }}\"></i>\r\n </a>\r\n <ngx-gallery-action *ngIf=\"zoom\" [icon]=\"zoomOutIcon\" [disabled]=\"!canZoomOut()\"\r\n (closeClick)=\"zoomOut()\"></ngx-gallery-action>\r\n <ngx-gallery-action *ngIf=\"zoom\" [icon]=\"zoomInIcon\" [disabled]=\"!canZoomIn()\"\r\n (closeClick)=\"zoomIn()\"></ngx-gallery-action>\r\n <ngx-gallery-action *ngIf=\"rotate\" [icon]=\"rotateLeftIcon\" (closeClick)=\"rotateLeft()\"></ngx-gallery-action>\r\n <ngx-gallery-action *ngIf=\"rotate\" [icon]=\"rotateRightIcon\" (closeClick)=\"rotateRight()\"></ngx-gallery-action>\r\n <ngx-gallery-action *ngIf=\"fullscreen\" [icon]=\"'ngx-gallery-fullscreen ' + fullscreenIcon\"\r\n (closeClick)=\"manageFullscreen()\"></ngx-gallery-action>\r\n <ngx-gallery-action [icon]=\"'ngx-gallery-close ' + closeIcon\" (closeClick)=\"close()\"></ngx-gallery-action>\r\n </div>\r\n</div>\r\n<div class=\"ngx-spinner-wrapper ngx-gallery-center\" [class.ngx-gallery-active]=\"showSpinner\">\r\n <i class=\"ngx-gallery-icon ngx-gallery-spinner {{spinnerIcon}}\" aria-hidden=\"true\"></i>\r\n</div>\r\n<div class=\"ngx-gallery-preview-wrapper\" (click)=\"closeOnClick && close()\" (mouseup)=\"mouseUpHandler($event)\"\r\n (mousemove)=\"mouseMoveHandler($event)\" (touchend)=\"mouseUpHandler($event)\" (touchmove)=\"mouseMoveHandler($event)\">\r\n <div class=\"ngx-gallery-preview-img-wrapper\">\r\n <img *ngIf=\"src && type === 'image'\" #previewImage class=\"ngx-gallery-preview-img ngx-gallery-center\" [src]=\"src\"\r\n (click)=\"$event.stopPropagation()\" (mouseenter)=\"imageMouseEnter()\" (mouseleave)=\"imageMouseLeave()\"\r\n (mousedown)=\"mouseDownHandler($event)\" (touchstart)=\"mouseDownHandler($event)\"\r\n [class.ngx-gallery-active]=\"!loading\" [class.animation]=\"animation\" [class.ngx-gallery-grab]=\"canDragOnZoom()\"\r\n [style.transform]=\"getTransform()\" [style.left]=\"positionLeft + 'px'\" [style.top]=\"positionTop + 'px'\"/>\r\n <video *ngIf=\"src && type === 'video'\" #previewImage controls style=\"width: 100%; height: 100%;\"\r\n class=\"ngx-gallery-preview-img ngx-gallery-center\"\r\n (click)=\"$event.stopPropagation()\" (mouseenter)=\"imageMouseEnter()\" (mouseleave)=\"imageMouseLeave()\" (mousedown)=\"mouseDownHandler($event)\" (touchstart)=\"mouseDownHandler($event)\"\r\n [class.ngx-gallery-active]=\"!loading\" [class.animation]=\"animation\" [class.ngx-gallery-grab]=\"canDragOnZoom()\" [style.transform]=\"getTransform()\" [style.left]=\"positionLeft + 'px'\" [style.top]=\"positionTop + 'px'\">\r\n <source [src]=\"src\">\r\n Your browser does not support the video tag.\r\n </video>\r\n <ngx-gallery-bullets *ngIf=\"bullets\" [count]=\"images.length\" [active]=\"index\"\r\n (bulletChange)=\"showAtIndex($event)\"></ngx-gallery-bullets>\r\n </div>\r\n <div class=\"ngx-gallery-preview-text\" *ngIf=\"showDescription && description\" [innerHTML]=\"description\"\r\n (click)=\"$event.stopPropagation()\"></div>\r\n</div>\r\n","export class NgxGalleryAnimation {\r\n static Fade = 'fade';\r\n static Slide = 'slide';\r\n static Rotate = 'rotate';\r\n static Zoom = 'zoom';\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n HostListener,\r\n Input,\r\n OnChanges,\r\n OnInit,\r\n Output,\r\n SimpleChanges\r\n} from '@angular/core';\r\nimport {DomSanitizer, SafeResourceUrl, SafeStyle} from '@angular/platform-browser';\r\nimport {NgxGalleryService} from '../ngx-gallery.service';\r\nimport {NgxGalleryOrderedImage} from '../ngx-gallery-ordered-image';\r\nimport {NgxGalleryAction} from '../ngx-gallery-action';\r\nimport {NgxGalleryAnimation} from '../ngx-gallery-animation';\r\nimport {animate, AnimationEvent, state, style, transition, trigger} from '@angular/animations';\r\n\r\ntype Orientation = ('slideLeft' | 'slideRight' | 'fade' | 'rotateLeft' | 'rotateRight' | 'zoom' | 'none');\r\n\r\n@Component({\r\n selector: 'ngx-gallery-image',\r\n templateUrl: './ngx-gallery-image.component.html',\r\n styleUrls: ['./ngx-gallery-image.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n animations: [\r\n trigger('animation', [\r\n // ...\r\n state('slideRight', style({})),\r\n state('slideLeft', style({})),\r\n state('fade', style({})),\r\n state('rotateLeft', style({})),\r\n state('rotateRight', style({})),\r\n state('zoom', style({})),\r\n transition('slideRight => void', [\r\n animate('500ms ease-in-out', style({transform: 'translateX(-100%)'}))\r\n ]),\r\n transition('void => slideRight', [\r\n style({transform: 'translateX(100%)'}),\r\n animate('500ms ease-in-out', style({transform: 'translateX(0)'}))\r\n ]),\r\n transition('slideLeft => void', [\r\n animate('500ms ease-in-out', style({transform: 'translateX(100%)'}))\r\n ]),\r\n transition('void => slideLeft', [\r\n style({transform: 'translateX(-100%)'}),\r\n animate('500ms ease-in-out', style({transform: 'translateX(0)'}))\r\n ]),\r\n transition('fade => void', [\r\n animate('500ms ease-in-out', style({opacity: '0'}))\r\n ]),\r\n transition('void => fade', [\r\n style({opacity: '0'}),\r\n animate('500ms ease-in-out', style({opacity: '1'}))\r\n ]),\r\n transition('rotateLeft => void', [\r\n animate('500ms ease-in-out', style({transform: 'scale(1, 1) rotate(-90deg)', opacity: '0'}))\r\n ]),\r\n transition('void => rotateLeft', [\r\n style({transform: 'scale(1, 1) rotate(-90deg)', opacity: '0'}),\r\n animate('500ms ease-in-out', style({transform: 'scale(1, 1) rotate(0deg)', opacity: '1'}))\r\n ]),\r\n transition('rotateRight => void', [\r\n animate('500ms ease-in-out', style({transform: 'scale(1, 1) rotate(90deg)', opacity: '0'}))\r\n ]),\r\n transition('void => rotateRight', [\r\n style({transform: 'scale(1, 1) rotate(90deg)', opacity: '0'}),\r\n animate('500ms ease-in-out', style({transform: 'scale(1, 1) rotate(0deg)', opacity: '1'}))\r\n ]),\r\n transition('zoom => void', [\r\n animate('500ms ease-in-out', style({transform: 'scale(2.5,2.5)', opacity: '0'}))\r\n ]),\r\n transition('void => zoom', [\r\n style({transform: 'scale(2.5,2.5)', opacity: '0'}),\r\n animate('500ms ease-in-out', style({transform: 'scale(1, 1)', opacity: '1'}))\r\n ]),\r\n ]),\r\n ]\r\n})\r\nexport class NgxGalleryImageComponent implements OnInit, OnChanges {\r\n @Input() images: NgxGalleryOrderedImage[];\r\n @Input() clickable: boolean;\r\n // eslint-disable-next-line @typescript-eslint/naming-convention, no-underscore-dangle, id-blacklist, id-match\r\n _selectedIndex;\r\n @Input()\r\n set selectedIndex(index: number) {\r\n if (index > this._selectedIndex) {\r\n let action;\r\n if (this.animation === NgxGalleryAnimation.Slide) {\r\n action = 'slideRight';\r\n } else if (this.animation === NgxGalleryAnimation.Fade) {\r\n action = 'fade';\r\n } else if (this.animation === NgxGalleryAnimation.Rotate) {\r\n action = 'rotateRight';\r\n } else if (this.animation === NgxGalleryAnimation.Zoom) {\r\n action = 'zoom';\r\n }\r\n this.setAction(action);\r\n } else if (index < this._selectedIndex) {\r\n let action;\r\n if (this.animation === NgxGalleryAnimation.Slide) {\r\n action = 'slideLeft';\r\n } else if (this.animation === NgxGalleryAnimation.Fade) {\r\n action = 'fade';\r\n } else if (this.animation === NgxGalleryAnimation.Rotate) {\r\n action = 'rotateLeft';\r\n } else if (this.animation === NgxGalleryAnimation.Zoom) {\r\n action = 'zoom';\r\n }\r\n this.setAction(action);\r\n }\r\n\r\n this._selectedIndex = index;\r\n }\r\n\r\n @Input() arrows: boolean;\r\n @Input() arrowsAutoHide: boolean;\r\n @Input() swipe: boolean;\r\n @Input() animation: string;\r\n @Input() size: string;\r\n @Input() arrowPrevIcon: string;\r\n @Input() arrowNextIcon: string;\r\n @Input() autoPlay: boolean;\r\n @Input() autoPlayInterval: number;\r\n @Input() autoPlayPauseOnHover: boolean;\r\n @Input() infinityMove: boolean;\r\n @Input() lazyLoading: boolean;\r\n @Input() actions: NgxGalleryAction[];\r\n @Input() descriptions: string[];\r\n @Input() showDescription: boolean;\r\n @Input() bullets: boolean;\r\n\r\n @Output() imageClick = new EventEmitter();\r\n @Output() activeChange = new EventEmitter();\r\n @Output() animating = new EventEmitter();\r\n\r\n canChangeImage = true;\r\n public action: Orientation;\r\n\r\n isAnimating = false;\r\n\r\n private timer;\r\n\r\n constructor(private sanitization: DomSanitizer, private changeDetectorRef: ChangeDetectorRef,\r\n private elementRef: ElementRef, private helperService: NgxGalleryService) {\r\n this.changeDetectorRef = changeDetectorRef;\r\n this.action = 'none';\r\n }\r\n\r\n // @HostBinding('style.display') public display = 'inline-block';\r\n // @HostBinding('style.background-color') public color = 'lime';\r\n\r\n ngOnInit() {\r\n if (this.arrows && this.arrowsAutoHide) {\r\n this.arrows = false;\r\n }\r\n\r\n if (this.autoPlay) {\r\n this.startAutoPlay();\r\n }\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['swipe']) {\r\n this.helperService.manageSwipe(this.swipe, this.elementRef, 'image', () => this.showNext(), () => this.showPrev());\r\n }\r\n }\r\n\r\n @HostListener('mouseenter') onMouseEnter() {\r\n if (this.arrowsAutoHide && !this.arrows) {\r\n this.arrows = true;\r\n }\r\n\r\n if (this.autoPlay && this.autoPlayPauseOnHover) {\r\n this.stopAutoPlay();\r\n }\r\n }\r\n\r\n @HostListener('mouseleave') onMouseLeave() {\r\n if (this.arrowsAutoHide && this.arrows) {\r\n this.arrows = false;\r\n }\r\n\r\n if (this.autoPlay && this.autoPlayPauseOnHover) {\r\n this.startAutoPlay();\r\n }\r\n }\r\n\r\n reset(index: number): void {\r\n this._selectedIndex = index;\r\n this.action = 'none';\r\n }\r\n\r\n getImages(): NgxGalleryOrderedImage[] {\r\n if (!this.images) {\r\n return [];\r\n }\r\n\r\n if (this.lazyLoading) {\r\n const indexes = [this._selectedIndex];\r\n const prevIndex = this._selectedIndex - 1;\r\n\r\n if (prevIndex === -1 && this.infinityMove) {\r\n indexes.push(this.images.length - 1);\r\n } else if (prevIndex >= 0) {\r\n indexes.push(prevIndex);\r\n }\r\n\r\n const nextIndex = this._selectedIndex + 1;\r\n\r\n if (nextIndex === this.images.length && this.infinityMove) {\r\n indexes.push(0);\r\n } else if (nextIndex < this.images.length) {\r\n indexes.push(nextIndex);\r\n }\r\n\r\n return this.images.filter((img, i) => indexes.indexOf(i) !== -1);\r\n } else {\r\n return this.images;\r\n }\r\n }\r\n\r\n startAutoPlay(): void {\r\n this.stopAutoPlay();\r\n\r\n this.timer = setInterval(() => {\r\n if (!this.showNext()) {\r\n this._selectedIndex = -1;\r\n this.showNext();\r\n }\r\n }, this.autoPlayInterval);\r\n }\r\n\r\n stopAutoPlay() {\r\n if (this.timer) {\r\n clearInterval(this.timer);\r\n }\r\n }\r\n\r\n handleClick(event: Event, index: number): void {\r\n if (this.clickable) {\r\n this.imageClick.emit(index);\r\n\r\n event.stopPropagation();\r\n event.preventDefault();\r\n }\r\n }\r\n\r\n show(index: number) {\r\n if (this.isAnimating) {\r\n return;\r\n }\r\n if (index > this._selectedIndex) {\r\n let action;\r\n if (this.animation === NgxGalleryAnimation.Slide) {\r\n action = 'slideRight';\r\n } else if (this.animation === NgxGalleryAnimation.Fade) {\r\n action = 'fade';\r\n } else if (this.animation === NgxGalleryAnimation.Rotate) {\r\n action = 'rotateRight';\r\n } else if (this.animation === NgxGalleryAnimation.Zoom) {\r\n action = 'zoom';\r\n }\r\n this.setAction(action);\r\n } else {\r\n let action;\r\n if (this.animation === NgxGalleryAnimation.Slide) {\r\n action = 'slideLeft';\r\n } else if (this.animation === NgxGalleryAnimation.Fade) {\r\n action = 'fade';\r\n } else if (this.animation === NgxGalleryAnimation.Rotate) {\r\n action = 'rotateLeft';\r\n } else if (this.animation === NgxGalleryAnimation.Zoom) {\r\n action = 'zoom';\r\n }\r\n this.setAction(action);\r\n }\r\n\r\n this._selectedIndex = index;\r\n this.activeChange.emit(this._selectedIndex);\r\n this.setChangeTimeout();\r\n }\r\n\r\n setAction(action: Orientation) {\r\n this.action = action;\r\n this.changeDetectorRef.detectChanges();\r\n }\r\n\r\n showNext(): boolean {\r\n if (this.isAnimating) {\r\n return false;\r\n }\r\n if (this.canShowNext() && this.canChangeImage) {\r\n let action;\r\n if (this.animation === NgxGalleryAnimation.Slide) {\r\n action = 'slideRight';\r\n } else if (this.animation === NgxGalleryAnimation.Fade) {\r\n action = 'fade';\r\n } else if (this.animation === NgxGalleryAnimation.Rotate) {\r\n action = 'rotateRight';\r\n } else if (this.animation === NgxGalleryAnimation.Zoom) {\r\n action = 'zoom';\r\n }\r\n this.setAction(action);\r\n this._selectedIndex++;\r\n if (this._selectedIndex === this.images.length) {\r\n this._selectedIndex = 0;\r\n }\r\n\r\n this.activeChange.emit(this._selectedIndex);\r\n this.setChangeTimeout();\r\n\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n showPrev(): void {\r\n if (this.isAnimating) {\r\n return;\r\n }\r\n if (this.canShowPrev() && this.canChangeImage) {\r\n let action;\r\n if (this.animation === NgxGalleryAnimation.Slide) {\r\n action = 'slideLeft';\r\n } else if (this.animation === NgxGalleryAnimation.Fade) {\r\n action = 'fade';\r\n } else if (this.animation === NgxGalleryAnimation.Rotate) {\r\n action = 'rotateLeft';\r\n } else if (this.animation === NgxGalleryAnimation.Zoom) {\r\n action = 'zoom';\r\n }\r\n this.setAction(action);\r\n this._selectedIndex--;\r\n if (this._selectedIndex < 0) {\r\n this._selectedIndex = this.images.length - 1;\r\n }\r\n\r\n this.activeChange.emit(this._selectedIndex);\r\n this.setChangeTimeout();\r\n }\r\n }\r\n\r\n setChangeTimeout() {\r\n this.canChangeImage = false;\r\n let timeout = 1000;\r\n\r\n if (this.animation === NgxGalleryAnimation.Slide\r\n || this.animation === NgxGalleryAnimation.Fade) {\r\n timeout = 500;\r\n }\r\n\r\n setTimeout(() => {\r\n this.canChangeImage = true;\r\n }, timeout);\r\n }\r\n\r\n canShowNext(): boolean {\r\n if (this.images) {\r\n return this.infinityMove || this._selectedIndex < this.images.length - 1;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n canShowPrev(): boolean {\r\n if (this.images) {\r\n return this.infinityMove || this._selectedIndex > 0;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n getSafeUrl(image: string | SafeResourceUrl): SafeStyle {\r\n return this.sanitization.bypassSecurityTrustStyle(this.helperService.getBackgroundUrl(image.toString()));\r\n }\r\n\r\n getFileType(fileSource: string) {\r\n return this.helperService.getFileType(fileSource);\r\n }\r\n\r\n onStart(event: AnimationEvent) {\r\n this.isAnimating = true;\r\n this.animating.emit(true);\r\n }\r\n\r\n onDone(event: AnimationEvent) {\r\n this.isAnimating = false;\r\n this.animating.emit(false);\r\n }\r\n}\r\n","<div class=\"ngx-gallery-image-wrapper ngx-gallery-animation-{{animation}} ngx-gallery-image-size-{{size}}\">\r\n <ng-container *ngFor=\"let image of getImages(); let i = index;\">\r\n\r\n <div *ngIf=\"image.type === 'image' && image.index === _selectedIndex\" class=\"ngx-gallery-image\"\r\n [ngClass]=\"{'ngx-gallery-clickable': clickable }\"\r\n [style.background-image]=\"getSafeUrl(image.src)\"\r\n (click)=\"handleClick($event, image.index)\"\r\n [@animation]=\"action\"\r\n (@animation.start)=\"onStart($event)\"\r\n (@animation.done)=\"onDone($event)\">\r\n <div class=\"ngx-gallery-icons-wrapper\">\r\n <ngx-gallery-action *ngFor=\"let action of actions\" [icon]=\"action.icon\" [disabled]=\"action.disabled\"\r\n [titleText]=\"action.titleText\"\r\n (closeClick)=\"action.onClick($event, image.index)\"></ngx-gallery-action>\r\n </div>\r\n <div class=\"ngx-gallery-image-text\" *ngIf=\"showDescription && descriptions[image.index]\"\r\n [innerHTML]=\"descriptions[image.index]\" (click)=\"$event.stopPropagation()\"></div>\r\n </div>\r\n\r\n <div *ngIf=\"image.type === 'video' && image.index === _selectedIndex\" class=\"ngx-gallery-image\"\r\n [ngClass]=\"{'ngx-gallery-clickable': clickable }\"\r\n [style.background-image]=\"getSafeUrl(image.src)\"\r\n (click)=\"handleClick($event, image.index)\"\r\n [@animation]=\"action\"\r\n (@animation.start)=\"onStart($event)\"\r\n (@animation.done)=\"onDone($event)\">\r\n <video controls style=\"width:100%; height:100%; background: #000;\">\r\n <source [src]=\"image.src\">\r\n Your browser does not support the video tag.\r\n </video>\r\n <div class=\"ngx-gallery-icons-wrapper\">\r\n <ngx-gallery-action *ngFor=\"let action of actions\" [icon]=\"action.icon\" [disabled]=\"action.disabled\"\r\n [titleText]=\"action.titleText\"\r\n (closeClick)=\"action.onClick($event, image.index)\"></ngx-gallery-action>\r\n </div>\r\n <div class=\"ngx-gallery-image-text\" *ngIf=\"showDescription && descriptions[image.index]\"\r\n [innerHTML]=\"descriptions[image.index]\" (click)=\"$event.stopPropagation()\"></div>\r\n </div>\r\n\r\n\r\n </ng-container>\r\n <ngx-gallery-bullets *ngIf=\"bullets\" [count]=\"images.length\" [active]=\"_selectedIndex\"\r\n (bulletChange)=\"show($event)\"></ngx-gallery-bullets>\r\n <ngx-gallery-arrows class=\"ngx-gallery-image-size-{{size}}\" *ngIf=\"arrows\" (prevClick)=\"showPrev()\"\r\n (nextClick)=\"showNext()\" [prevDisabled]=\"!canShowPrev()\" [nextDisabled]=\"!canShowNext()\"\r\n [arrowPrevIcon]=\"arrowPrevIcon\" [arrowNextIcon]=\"arrowNextIcon\"></ngx-gallery-arrows>\r\n</div>\r\n","export class NgxGalleryOrder {\r\n static Column = 1;\r\n static Row = 2;\r\n static Page = 3;\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n HostListener,\r\n Input,\r\n OnChanges,\r\n OnInit,\r\n Output,\r\n SimpleChanges\r\n} from '@angular/core';\r\nimport {DomSanitizer, SafeResourceUrl, SafeStyle} from '@angular/platform-browser';\r\nimport {NgxGalleryService} from '../ngx-gallery.service';\r\nimport {NgxGalleryAction} from '../ngx-gallery-action';\r\nimport {NgxGalleryOrder} from '../ngx-gallery-order';\r\n\r\n@Component({\r\n selector: 'ngx-gallery-thumbnails',\r\n templateUrl: './ngx-gallery-thumbnails.component.html',\r\n styleUrls: ['./ngx-gallery-thumbnails.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class NgxGalleryThumbnailsComponent implements OnChanges {\r\n thumbnailsLeft: string;\r\n thumbnailsMarginLeft: string;\r\n mouseenter: boolean;\r\n remainingCountValue: number;\r\n\r\n minStopIndex = 0;\r\n\r\n @Input() images: string[] | SafeResourceUrl[];\r\n @Input() isAnimating: boolean;\r\n @Input() links: string[];\r\n @Input() labels: string[];\r\n @Input() linkTarget: string;\r\n @Input() columns: number;\r\n @Input() rows: number;\r\n @Input() arrows: boolean;\r\n @Input() arrowsAutoHide: boolean;\r\n @Input() margin: number;\r\n @Input() selectedIndex: number;\r\n @Input() clickable: boolean;\r\n @Input() swipe: boolean;\r\n @Input() size: string;\r\n @Input() arrowPrevIcon: string;\r\n @Input() arrowNextIcon: string;\r\n @Input() moveSize: number;\r\n @Input() order: number;\r\n @Input() remainingCount: boolean;\r\n @Input() lazyLoading: boolean;\r\n @Input() actions: NgxGalleryAction[];\r\n\r\n @Output() activeChange = new EventEmitter();\r\n\r\n private index = 0;\r\n\r\n constructor(private sanitization: DomSanitizer, private elementRef: ElementRef,\r\n private helperService: NgxGalleryService) {\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['selectedIndex']) {\r\n this.validateIndex();\r\n }\r\n\r\n if (changes['swipe']) {\r\n this.helperService.manageSwipe(this.swipe, this.elementRef,\r\n 'thumbnails', () => this.moveRight(), () => this.moveLeft());\r\n }\r\n\r\n if (this.images) {\r\n this.remainingCountValue = this.images.length - (this.rows * this.columns);\r\n }\r\n }\r\n\r\n @HostListener('mouseenter') onMouseEnter() {\r\n this.mouseenter = true;\r\n }\r\n\r\n @HostListener('mouseleave') onMouseLeave() {\r\n this.mouseenter = false;\r\n }\r\n\r\n reset(index: number): void {\r\n this.selectedIndex = index;\r\n this.setDefaultPosition();\r\n\r\n this.index = 0;\r\n this.validateIndex();\r\n }\r\n\r\n getImages(): string[] | SafeResourceUrl[] {\r\n if (!this.images) {\r\n return [];\r\n }\r\n\r\n if (this.remainingCount) {\r\n return this.images.slice(0, this.rows * this.columns);\r\n } else if (this.lazyLoading && this.order !== NgxGalleryOrder.Row) {\r\n let stopIndex = 0;\r\n\r\n if (this.order === NgxGalleryOrder.Column) {\r\n stopIndex = (this.index + this.columns + this.moveSize) * this.rows;\r\n } else if (this.order === NgxGalleryOrder.Page) {\r\n stopIndex = this.index + ((this.columns * this.rows) * 2);\r\n }\r\n\r\n if (stopIndex <= this.minStopIndex) {\r\n stopIndex = this.minStopIndex;\r\n } else {\r\n this.minStopIndex = stopIndex;\r\n }\r\n\r\n return this.images.slice(0, stopIndex);\r\n } else {\r\n return this.images;\r\n }\r\n }\r\n\r\n handleClick(event: Event, index: number): void {\r\n if (!this.hasLink(index) && !this.isAnimating) {\r\n this.selectedIndex = index;\r\n this.activeChange.emit(index);\r\n }\r\n event.stopPropagation();\r\n event.preventDefault();\r\n }\r\n\r\n hasLink(index: number): boolean {\r\n return !!(this.links && this.links.length && this.links[index]);\r\n }\r\n\r\n moveRight(): void {\r\n if (this.canMoveRight()) {\r\n this.index += this.moveSize;\r\n const maxIndex = this.getMaxIndex() - this.columns;\r\n\r\n if (this.index > maxIndex) {\r\n this.index = maxIndex;\r\n }\r\n\r\n this.setThumbnailsPosition();\r\n }\r\n }\r\n\r\n moveLeft(): void {\r\n if (this.canMoveLeft()) {\r\n this.index -= this.moveSize;\r\n\r\n if (this.index < 0) {\r\n this.index = 0;\r\n }\r\n\r\n this.setThumbnailsPosition();\r\n }\r\n }\r\n\r\n canMoveRight(): boolean {\r\n return this.index + this.columns < this.getMaxIndex();\r\n }\r\n\r\n canMoveLeft(): boolean {\r\n return this.index !== 0;\r\n }\r\n\r\n getThumbnailLeft(index: number): SafeStyle {\r\n let calculatedIndex;\r\n\r\n if (this.order === NgxGalleryOrder.Column) {\r\n calculatedIndex = Math.floor(index / this.rows);\r\n } else if (this.order === NgxGalleryOrder.Page) {\r\n calculatedIndex = (index % this.columns) + (Math.floor(index / (this.rows * this.columns)) * this.columns);\r\n } else if (this.order === NgxGalleryOrder.Row && this.remainingCount) {\r\n calculatedIndex = index % this.columns;\r\n } else {\r\n calculatedIndex = index % Math.ceil(this.images.length / this.rows);\r\n }\r\n\r\n return this.getThumbnailPosition(calculatedIndex, this.columns);\r\n }\r\n\r\n getThumbnailTop(index: number): SafeStyle {\r\n let calculatedIndex;\r\n\r\n if (this.order === NgxGalleryOrder.Column) {\r\n calculatedIndex = index % this.rows;\r\n } else if (this.order === NgxGalleryOrder.Page) {\r\n calculatedIndex = Math.floor(index / this.columns) - (Math.floor(index / (this.rows * this.columns)) * this.rows);\r\n } else if (this.order === NgxGalleryOrder.Row && this.remainingCount) {\r\n calculatedIndex = Math.floor(index / this.columns);\r\n } else {\r\n calculatedIndex = Math.floor(index / Math.ceil(this.images.length / this.rows));\r\n }\r\n\r\n return this.getThumbnailPosition(calculatedIndex, this.rows);\r\n }\r\n\r\n getThumbnailWidth(): SafeStyle {\r\n return this.getThumbnailDimension(this.columns);\r\n }\r\n\r\n getThumbnailHeight(): SafeStyle {\r\n return this.getThumbnailDimension(this.rows);\r\n }\r\n\r\n setThumbnailsPosition(): void {\r\n this.thumbnailsLeft = -((100 / this.columns) * this.index) + '%';\r\n\r\n this.thumbnailsMarginLeft = -((this.margin - (((this.columns - 1)\r\n * this.margin) / this.columns)) * this.index) + 'px';\r\n }\r\n\r\n setDefaultPosition(): void {\r\n this.thumbnailsLeft = '0px';\r\n this.thumbnailsMarginLeft = '0px';\r\n }\r\n\r\n canShowArrows(): boolean {\r\n if (this.remainingCount) {\r\n return false;\r\n } else {\r\n return this.arrows && this.images && this.images.length > this.getVisibleCount()\r\n && (!this.arrowsAutoHide || this.mouseenter);\r\n }\r\n }\r\n\r\n validateIndex(): void {\r\n if (this.images) {\r\n let newIndex;\r\n\r\n if (this.order === NgxGalleryOrder.Column) {\r\n newIndex = Math.floor(this.selectedIndex / this.rows);\r\n } else {\r\n newIndex = this.selectedIndex % Math.ceil(this.images.length / this.rows);\r\n }\r\n\r\n if (this.remainingCount) {\r\n newIndex = 0;\r\n }\r\n\r\n if (newIndex < this.index || newIndex >= this.index + this.columns) {\r\n const maxIndex = this.getMaxIndex() - this.columns;\r\n this.index = newIndex > maxIndex ? maxIndex : newIndex;\r\n\r\n this.setThumbnailsPosition();\r\n }\r\n }\r\n }\r\n\r\n getSafeUrl(image: string | SafeResourceUrl): SafeStyle {\r\n return this.sanitization.bypassSecurityTrustStyle(this.helperService.getBackgroundUrl(image.toString()));\r\n }\r\n\r\n getFileType(fileSource: string | SafeResourceUrl): string {\r\n return this.helperService.getFileType(fileSource.toString());\r\n }\r\n\r\n private getThumbnailPosition(index: number, count: number): SafeStyle {\r\n return this.getSafeStyle('calc(' + ((100 / count) * index) + '% + '\r\n + ((this.margin - (((count - 1) * this.margin) / count)) * index) + 'px)');\r\n }\r\n\r\n private getThumbnailDimension(count: number): SafeStyle {\r\n if (this.margin !== 0) {\r\n return this.getSafeStyle('calc(' + (100 / count) + '% - '\r\n + (((count - 1) * this.margin) / count) + 'px)');\r\n } else {\r\n return this.getSafeStyle('calc(' + (100 / count) + '% + 1px)');\r\n }\r\n }\r\n\r\n private getMaxIndex(): number {\r\n if (this.order === NgxGalleryOrder.Page) {\r\n let maxIndex = (Math.floor(this.images.length / this.getVisibleCount()) * this.columns);\r\n\r\n if (this.images.length % this.getVisibleCount() > this.columns) {\r\n maxIndex += this.columns;\r\n } else {\r\n maxIndex += this.images.length % this.getVisibleCount();\r\n }\r\n\r\n return maxIndex;\r\n } else {\r\n return Math.ceil(this.images.length / this.rows);\r\n }\r\n }\r\n\r\n private getVisibleCount(): number {\r\n return this.columns * this.rows;\r\n }\r\n\r\n private getSafeStyle(value: string): SafeStyle {\r\n return this.sanitization.bypassSecurityTrustStyle(value);\r\n }\r\n}\r\n","<div class=\"ngx-gallery-thumbnails-wrapper ngx-gallery-thumbnail-size-{{size}}\">\r\n <div class=\"ngx-gallery-thumbnails\" [style.transform]=\"'translateX(' + thumbnailsLeft + ')'\"\r\n [style.marginLeft]=\"thumbnailsMarginLeft\">\r\n <a [href]=\"hasLink(i) ? links[i] : '#'\" [target]=\"linkTarget\" class=\"ngx-gallery-thumbnail\"\r\n *ngFor=\"let image of getImages(); let i = index;\"\r\n (click)=\"handleClick($event, i)\" [style.width]=\"getThumbnailWidth()\" [style.height]=\"getThumbnailHeight()\"\r\n [style.left]=\"getThumbnailLeft(i)\" [style.top]=\"getThumbnailTop(i)\"\r\n [ngClass]=\"{ 'ngx-gallery-active': i === selectedIndex, 'ngx-gallery-clickable': clickable }\"\r\n [attr.aria-label]=\"labels[i]\">\r\n <div *ngIf=\"getFileType(image) === 'image'\" [style.background-image]=\"getSafeUrl(image)\" class=\"ng