UNPKG

angular-gallery

Version:

Responsive gallery for Angular with touch screen support.

1,262 lines (1,256 loc) 56.9 kB
import { __decorate } from 'tslib'; import { Injectable, EventEmitter, ElementRef, ChangeDetectorRef, Input, Output, HostBinding, HostListener, Component, ViewContainerRef, Directive, ComponentFactoryResolver, ViewChild, ApplicationRef, Injector, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ReplaySubject } from 'rxjs'; class Touches { constructor(properties) { this.eventType = undefined; this.handlers = {}; this.startX = 0; this.startY = 0; this.lastTap = 0; this.doubleTapMinTimeout = 300; this.tapMinTimeout = 200; this.touchstartTime = 0; this.i = 0; this.isMousedown = false; this.touchListeners = { "touchstart": "handleTouchstart", "touchmove": "handleTouchmove", "touchend": "handleTouchend" }; this.mouseListeners = { "mousedown": "handleMousedown", "mousemove": "handleMousemove", "mouseup": "handleMouseup", "wheel": "handleWheel" }; this.otherListeners = { "resize": "handleResize" }; /* * Listeners */ /* Touchstart */ this.handleTouchstart = (event) => { this.elementPosition = this.getElementPosition(); this.touchstartTime = new Date().getTime(); if (this.eventType === undefined) { this.getTouchstartPosition(event); } this.runHandler("touchstart", event); }; /* Touchmove */ this.handleTouchmove = (event) => { const touches = event.touches; // Pan if (this.detectPan(touches)) { this.runHandler("pan", event); } // Pinch if (this.detectPinch(event)) { this.runHandler("pinch", event); } // Linear swipe switch (this.detectLinearSwipe(event)) { case "horizontal-swipe": event.swipeType = "horizontal-swipe"; this.runHandler("horizontal-swipe", event); break; case "vertical-swipe": event.swipeType = "vertical-swipe"; this.runHandler("vertical-swipe", event); break; } // Linear swipe if (this.detectLinearSwipe(event) || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') { this.handleLinearSwipe(event); } }; /* Touchend */ this.handleTouchend = (event) => { const touches = event.touches; // Double Tap if (this.detectDoubleTap()) { this.runHandler("double-tap", event); } // Tap this.detectTap(); this.runHandler("touchend", event); this.eventType = 'touchend'; if (touches && touches.length === 0) { this.eventType = undefined; this.i = 0; } }; /* Mousedown */ this.handleMousedown = (event) => { this.isMousedown = true; this.elementPosition = this.getElementPosition(); this.touchstartTime = new Date().getTime(); if (this.eventType === undefined) { this.getMousedownPosition(event); } this.runHandler("mousedown", event); }; /* Mousemove */ this.handleMousemove = (event) => { //event.preventDefault(); if (!this.isMousedown) { return; } // Pan this.runHandler("pan", event); // Linear swipe switch (this.detectLinearSwipe(event)) { case "horizontal-swipe": event.swipeType = "horizontal-swipe"; this.runHandler("horizontal-swipe", event); break; case "vertical-swipe": event.swipeType = "vertical-swipe"; this.runHandler("vertical-swipe", event); break; } // Linear swipe if (this.detectLinearSwipe(event) || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') { this.handleLinearSwipe(event); } }; /* Mouseup */ this.handleMouseup = (event) => { // Tap this.detectTap(); this.isMousedown = false; this.runHandler("mouseup", event); this.eventType = undefined; this.i = 0; }; /* Wheel */ this.handleWheel = (event) => { this.runHandler("wheel", event); }; /* Resize */ this.handleResize = (event) => { this.runHandler("resize", event); }; this.properties = properties; this.element = this.properties.element; this.elementPosition = this.getElementPosition(); this.toggleEventListeners('addEventListener'); } destroy() { this.toggleEventListeners('removeEventListener'); } toggleEventListeners(action) { let listeners; if (this.properties.listeners === 'mouse and touch') { listeners = Object.assign(this.touchListeners, this.mouseListeners); } else { listeners = this.detectTouchScreen() ? this.touchListeners : this.mouseListeners; } if (this.properties.resize) { listeners = Object.assign(listeners, this.otherListeners); } for (var listener in listeners) { const handler = listeners[listener]; // Window if (listener === "resize") { if (action === 'addEventListener') { window.addEventListener(listener, this[handler], false); } if (action === 'removeEventListener') { window.removeEventListener(listener, this[handler], false); } // Document } else if (listener === 'mouseup' || listener === "mousemove") { if (action === 'addEventListener') { document.addEventListener(listener, this[handler], false); } if (action === 'removeEventListener') { document.removeEventListener(listener, this[handler], false); } // Element } else { if (action === 'addEventListener') { this.element.addEventListener(listener, this[handler], false); } if (action === 'removeEventListener') { this.element.removeEventListener(listener, this[handler], false); } } } } handleLinearSwipe(event) { //event.preventDefault(); this.i++; if (this.i > 3) { this.eventType = this.getLinearSwipeType(event); } if (this.eventType === 'horizontal-swipe') { this.runHandler('horizontal-swipe', event); } if (this.eventType === 'vertical-swipe') { this.runHandler('vertical-swipe', event); } } runHandler(eventName, response) { if (this.handlers[eventName]) { this.handlers[eventName](response); } } /* * Detection */ detectPan(touches) { return touches.length === 1 && !this.eventType || this.eventType === 'pan'; } detectDoubleTap() { if (this.eventType != undefined) { return; } const currentTime = new Date().getTime(); const tapLength = currentTime - this.lastTap; clearTimeout(this.doubleTapTimeout); if (tapLength < this.doubleTapMinTimeout && tapLength > 0) { return true; } else { this.doubleTapTimeout = setTimeout(() => { clearTimeout(this.doubleTapTimeout); }, this.doubleTapMinTimeout); } this.lastTap = currentTime; } detectTap() { if (this.eventType != undefined) { return; } const currentTime = new Date().getTime(); const tapLength = currentTime - this.touchstartTime; if (tapLength > 0) { if (tapLength < this.tapMinTimeout) { this.runHandler("tap", event); } else { this.runHandler("longtap", event); } } } detectPinch(event) { const touches = event.touches; return (touches.length === 2 && this.eventType === undefined) || this.eventType === 'pinch'; } detectLinearSwipe(event) { const touches = event.touches; if (touches) { if (touches.length === 1 && !this.eventType || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') { return this.getLinearSwipeType(event); } } else { if (!this.eventType || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') { return this.getLinearSwipeType(event); } } } getLinearSwipeType(event) { if (this.eventType !== 'horizontal-swipe' && this.eventType !== 'vertical-swipe') { const movementX = Math.abs(this.moveLeft(0, event) - this.startX); const movementY = Math.abs(this.moveTop(0, event) - this.startY); if ((movementY * 3) > movementX) { return 'vertical-swipe'; } else { return 'horizontal-swipe'; } } else { return this.eventType; } } getElementPosition() { return this.element.getBoundingClientRect(); } getTouchstartPosition(event) { this.startX = event.touches[0].clientX - this.elementPosition.left; this.startY = event.touches[0].clientY - this.elementPosition.top; } getMousedownPosition(event) { this.startX = event.clientX - this.elementPosition.left; this.startY = event.clientY - this.elementPosition.top; } moveLeft(index, event) { const touches = event.touches; if (touches) { return touches[index].clientX - this.elementPosition.left; } else { return event.clientX - this.elementPosition.left; } } moveTop(index, event) { const touches = event.touches; if (touches) { return touches[index].clientY - this.elementPosition.top; } else { return event.clientY - this.elementPosition.top; } } detectTouchScreen() { var prefixes = ' -webkit- -moz- -o- -ms- '.split(' '); var mq = function (query) { return window.matchMedia(query).matches; }; if (('ontouchstart' in window)) { return true; } // include the 'heartz' as a way to have a non matching MQ to help terminate the join // https://git.io/vznFH var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''); return mq(query); } /* Public properties and methods */ on(event, handler) { if (event) { this.handlers[event] = handler; } } } class Carousel { constructor(properties) { this.initialPositionX = 0; this.newContainerPositionIndex = 0; // The index of the new position relative to the active index, for example -1 or +1 this.preliminarySlideCounter = 0; this.slideCounter = 0; // Scrolling Index (counter) this.previousSlideCounter = 0; this.isContentImages = true; this.isLazyLoad = true; this.isContainerLocked = false; this.alignCells = "left"; this.initialContainerPosition = 0; this.handleTouchstart = (event) => { this.isTouchstart = true; if (this.isSlideInProgress) { return; } const touches = event.touches; if (touches) { this.startX = touches[0].clientX - this.getCarouselElementPosition()['left']; } else { this.startX = event.clientX - this.getCarouselElementPosition()['left']; } this.containerInitialPositionX = this.getElementPosition()['left'] - this.getCarouselElementPosition()['left']; this.isMoveInProgress = true; }; this.handleHorizontalSwipe = (event) => { if (this.isSlideInProgress) { return; } const touches = event.touches; if (touches) { this.moveX = touches[0].clientX - this.getCarouselElementPosition()['left']; } else { this.moveX = event.clientX - this.getCarouselElementPosition()['left']; } this.distanceAbs = this.getDistanceAbs(); this.direction = this.getDirection(); this.moveContainer(); }; this.handleTouchend = (event) => { if (this.isSlideInProgress || !this.isTouchstart) { this.isTouchstart = false; return; } this.isMoveInProgress = false; if (this.detectSlide()) { this.handleSlide(); } else { this.newContainerPositionIndex = 0; this.alignContainer(); } this.startX = this.moveX = this.distanceAbs = undefined; this.isTouchstart = false; }; this.element = properties.element; this.properties = properties; this.cells = this.element.children; this.visibleWidth = this.properties.visibleWidth || this.element.parentElement.clientWidth; this.setContainerWidth(); this.alignContainer(0); } get isFirstCell() { return this.slideCounter === 0; } get lastCellIndex() { return this.images.length ? (this.images.length - 1) : (this.cells.length - 1); } get overflowCellsLimit() { return this.properties.overflowCellsLimit; } get cellLimit() { return this.visibleCellsCount + this.overflowCellsLimit * 2; } get images() { return this.properties.images; } get margin() { return this.properties.margin; } get minSwipeDistance() { return this.properties.minSwipeDistance; } get transitionDuration() { return this.properties.transitionDuration; } get transitionTimingFunction() { return this.properties.transitionTimingFunction; } get fullCellWidth() { return this.properties.cellWidth + this.margin; } get visibleCellsCount() { return Math.ceil(this.visibleWidth / this.fullCellWidth); } get lapCounter() { return Math.floor(this.slideCounter / this.totalContainerCellsCount); } get visibleCellsOverflowContainer() { return (this.visibleCellsCount * this.fullCellWidth - this.margin) > this.visibleWidth; } /* Move */ moveContainer() { let positionX = this.getMovePositionX(); this.transformPositionX(positionX, 0); } getMovePositionX() { const distance = this.getDistance(); return this.containerInitialPositionX - distance; } /* Align */ alignContainer(duration = this.transitionDuration) { let positionX = this.getContainerPosition(); this.transformPositionX(positionX, duration); this.setInitialContainerPosition(positionX); } getContainerPosition() { let correction = this.getContainerPositionCorrection(); this.isContainerPositionCorrection = correction != 0; return (this.initialContainerPosition + this.newContainerPositionIndex * this.fullCellWidth) + correction; } setInitialContainerPosition(position) { let correction = this.getContainerPositionCorrection(); this.initialContainerPosition = position - correction; } getContainerPositionCorrection() { let correction = 0; if ((this.images.length - this.preliminarySlideCounter) < this.visibleCellsCount || this.isSlideLengthLimited) { if (this.visibleWidth < this.totalContainerCellsCount * this.fullCellWidth) { correction = -(this.visibleCellsCount * this.fullCellWidth - this.visibleWidth - this.margin); } if (correction >= -this.margin) { correction = 0; } } return correction; } /* Quickly center */ quicklyPositionContainer() { let correction = this.getContainerPositionCorrection(); const initialPosition = this.getNewContainerPosition() + correction; this.transformPositionX(initialPosition, 0); this.setInitialContainerPosition(initialPosition); } getNewContainerPosition() { if (this.slideCounter > this.overflowCellsLimit) { if (this.alignCells === "left") { this.lineUpCells(); return -(this.overflowCellsLimit * this.fullCellWidth); } } if (this.slideCounter <= this.overflowCellsLimit) { if (this.previousSlideCounter > this.overflowCellsLimit) { this.lineUpCells(); } return -(this.slideCounter * this.fullCellWidth); } } setContainerWidth() { const containerWidth = this.getContainerWidth(); this.element.style.width = containerWidth + "px"; } getContainerWidth() { this.totalContainerCellsCount = this.visibleCellsCount + this.overflowCellsLimit * 2; let containerWidth = this.totalContainerCellsCount * this.fullCellWidth; let totalImageWidth = this.images.length * this.fullCellWidth; if (totalImageWidth < containerWidth) { containerWidth = totalImageWidth; } return containerWidth; } getFile(cellIndex) { let imageIndex = this.getFileIndex(cellIndex); let file = this.images[imageIndex]; if (file && !file.type) { file.type = 'image'; } return { image: this.images[imageIndex], imageIndex }; } getFileIndex(cellIndex) { const positionIndex = this.getPositionIndex(cellIndex); const numberLeftCells = (this.totalContainerCellsCount - 1) / 2; let imageIndex; if (!this.isContainerLocked) { if (this.slideCounter <= this.overflowCellsLimit) { return cellIndex; } else { let cellLimitOverflow = this.slideCounter - this.overflowCellsLimit; imageIndex = positionIndex + cellLimitOverflow; return imageIndex; } } if (this.alignCells === "left") { if (this.slideCounter > this.overflowCellsLimit) { let cellLimitOverflow = this.slideCounter - this.overflowCellsLimit; imageIndex = positionIndex + cellLimitOverflow; } else { imageIndex = cellIndex; } } if (imageIndex > this.lastCellIndex) { return false; } return imageIndex; } transformPositionX(value, duration = this.transitionDuration) { this.element.style.transition = 'transform ' + duration + 'ms ' + this.transitionTimingFunction; this.element.style.transform = 'translateX(' + value + 'px)'; } detectSlide() { return this.distanceAbs >= this.minSwipeDistance; } next() { if (this.isSlideInProgress) { return; } this.direction = 'left'; this.handleSlide(1); } prev() { if (this.isSlideInProgress) { return; } this.direction = 'right'; this.handleSlide(1); } select(index) { this.slideCounter = index; this.quicklyPositionContainer(); } handleSlide(slideLength = undefined) { this.slideLength = this.getSlideLength(); this.slideLength = slideLength ? slideLength : this.limitSlideLength(this.slideLength); if (this.direction === 'left' && !this.isSlideInProgress) { this.preliminarySlideCounter = this.slideCounter + this.slideLength; if (!this.detectLastSlide(this.slideCounter + this.slideLength)) { this.newContainerPositionIndex = this.newContainerPositionIndex - this.slideLength; this.isSlideInProgress = true; if (this.isLazyLoad) { this.isContainerLocked = this.preliminarySlideCounter > this.overflowCellsLimit; if (this.detectContainerUnlock()) { this.isContainerLocked = false; } } } } if (this.direction === 'right' && !this.isSlideInProgress) { if (this.slideCounter - this.slideLength < 0) { this.slideLength = this.slideCounter; } this.preliminarySlideCounter = this.slideCounter - this.slideLength; if (!this.isFirstCell) { this.newContainerPositionIndex = this.newContainerPositionIndex + this.slideLength; this.isSlideInProgress = true; if (this.isLazyLoad) { if (this.preliminarySlideCounter > this.overflowCellsLimit) { this.isContainerLocked = true; } else { this.isContainerLocked = false; } if (this.detectContainerUnlock()) { this.isContainerLocked = false; } } } } this.alignContainer(); } getSlideLength() { let correction = this.getContainerPositionCorrection(); let length = Math.floor((this.distanceAbs + correction) / this.fullCellWidth); if (this.distanceAbs % this.fullCellWidth >= this.minSwipeDistance) { length++; } return length; } limitSlideLength(slideLength) { if (slideLength > 1) { for (var i = 0; i < slideLength; i++) { let newSlideCounter = this.slideCounter + (slideLength - i); if (!this.detectLastSlide(newSlideCounter)) { slideLength = slideLength - i; this.isSlideLengthLimited = i > 0; break; } } } return slideLength; } detectLastSlide(slideCounter) { return (this.images.length - slideCounter) < this.visibleCellsCount; } isNextArrowDisabled() { if (this.visibleCellsOverflowContainer) { return this.detectLastSlide(this.slideCounter + 1) && this.isContainerPositionCorrection; } else { return this.detectLastSlide(this.slideCounter + 1); } } isPrevArrowDisabled() { return this.slideCounter === 0; } detectContainerUnlock() { return (this.images.length - this.preliminarySlideCounter) < (this.visibleCellsCount + this.overflowCellsLimit); } handleSlideEnd() { if (this.isSlideInProgress) { this.transformSlideEnd(); this.isSlideInProgress = false; this.newContainerPositionIndex = 0; this.isSlideLengthLimited = undefined; } } transformSlideEnd() { if (this.isLazyLoad) { this.setSlideCounter(); this.quicklyPositionContainer(); } this.previousSlideCounter = this.slideCounter; } setSlideCounter() { if (this.direction === 'left') { this.slideCounter = this.slideCounter + this.slideLength; } if (this.direction === 'right') { this.slideCounter = this.slideCounter - this.slideLength; } this.direction = undefined; this.slideLength = 0; } resetTransition() { this.element.style.transition = ''; } getElementPosition() { return this.element.getBoundingClientRect(); } getCarouselElementPosition() { return this.properties.container.getBoundingClientRect(); } getDistance() { return this.startX - this.moveX; } getDistanceAbs() { return Math.abs(this.startX - this.moveX); } getDirection() { const direction = Math.sign(this.startX - this.moveX); if (direction === -1) { return 'right'; } if (direction === 1) { return 'left'; } } lineUpCells() { const cells = this.element.children; for (var i = 0; i < cells.length; i++) { let cell = cells[i]; let positionX = this.getCellPositionX(i); cell.style.transform = 'translateX(' + positionX + 'px)'; } ; } getCellPositionX(index) { let positionIndex = this.getPositionIndex(index); return positionIndex * this.fullCellWidth; } getPositionIndex(cellIndex) { let slideCounter = this.slideCounter - this.overflowCellsLimit; let positionIndex; if (slideCounter > this.totalContainerCellsCount) { slideCounter = slideCounter % this.totalContainerCellsCount; } if (slideCounter < 0) { return cellIndex; } else { positionIndex = cellIndex - slideCounter; if (positionIndex < 0) { positionIndex = this.totalContainerCellsCount + positionIndex; } } return positionIndex; } get containerOverflowRightCount() { let totalOverflowCellsCount = this.images.length - this.totalContainerCellsCount; let overflowRight = 0; if (totalOverflowCellsCount > 0) { overflowRight = totalOverflowCellsCount - (this.previousSlideCounter - this.overflowCellsLimit); if (overflowRight > 0) { return overflowRight; } } return overflowRight; } getCenterPositionIndex() { return (this.totalContainerCellsCount - 1) / 2; } } let EventService = class EventService { constructor() { this.emitter = new ReplaySubject(1); } emitChangeEvent(data) { this.emitter.next(data); } }; EventService = __decorate([ Injectable() ], EventService); let CarouselComponent = class CarouselComponent { constructor(elementRef, ref, overlayEventService) { this.elementRef = elementRef; this.ref = ref; this.overlayEventService = overlayEventService; this.minTimeout = 30; this._cellWidth = 200; this._transitionDuration = 200; this.events = new EventEmitter(); this.height = 200; this.margin = 10; this.objectFit = 'cover'; this.minSwipeDistance = 50; this.transitionTimingFunction = 'ease'; this.counterSeparator = " / "; this.overflowCellsLimit = 3; this.listeners = 'mouse and touch'; this.arrows = true; this.arrowsTheme = 'light'; this.hostClassCarousel = true; /* Touchstart */ this.handleTouchstart = (event) => { event.preventDefault(); this.carousel.handleTouchstart(event); this.isMoving = true; this.events.emit({ type: 'touchstart', event }); }; /* Touchmove */ this.handleHorizontalSwipe = (event) => { event.preventDefault(); this.carousel.handleHorizontalSwipe(event); this.events.emit({ type: 'swipe', event }); }; /* Touchend */ this.handleTouchend = (event) => { const touches = event.touches; this.carousel.handleTouchend(event); this.isMoving = false; this.events.emit({ type: 'touchend', event }); }; /* Tap */ this.handleTap = (event) => { const i = this.carousel.slideCounter; const cellIndex = this.carousel.currentCellIndex; const fileIndex = this.carousel.getFileIndex(i); const file = this.carousel.getFile(cellIndex); this.events.emit({ type: 'click', file: file, index: fileIndex }); }; } get isLandscape() { return window.innerWidth > window.innerHeight; } get isSafari() { const ua = navigator.userAgent.toLowerCase(); if (ua.indexOf('safari') !== -1) { return !(ua.indexOf('chrome') > -1); } } get counter() { return this.carousel.slideCounter + 1 + this.counterSeparator + this.images.length; } set images(images) { this._images = images; } get images() { return this._images; } get isNgContent() { return this.elementRef.nativeElement.querySelector('.carousel-content-wrapper').children.length > 0; } set transitionDuration(value) { this._transitionDuration = value; } get transitionDuration() { if (this._transitionDuration === 0) { return 1; } else { return this._transitionDuration; } } set cellWidth(value) { if (value) { this._cellWidth = value; } } set isCounter(value) { if (value) { this._isCounter = value; } } get isCounter() { return this._isCounter && this.images.length > 1; } set overlayProperties(properties) { this._properties = properties; this._images = this._properties.metadata.images; this._cellWidth = this._properties.metadata.width; this.height = this._properties.metadata.height; this.objectFit = this._properties.metadata.objectFit; this.margin = this._properties.metadata.margin; this.transitionDuration = this._properties.metadata.transitionDuration; this.overflowCellsLimit = this._properties.metadata.overflowCellsLimit; this.minSwipeDistance = this._properties.metadata.minSwipeDistance; this.transitionTimingFunction = this._properties.metadata.transitionTimingFunction; this._isCounter = this._properties.metadata.counter; this.counterSeparator = this._properties.metadata.counterSeparator; this.arrows = this._properties.metadata.arrows; } get properties() { return this._properties; } get cellLimit() { if (this.carousel) { return this.carousel.cellLimit; } } onWindowResize(event) { this.landscapeMode = this.isLandscape; this.ref.detectChanges(); this.initCarousel(); this.carousel.lineUpCells(); } ngOnInit() { this.touches = new Touches({ element: this.elementRef.nativeElement.querySelector('.carousel-cells'), listeners: this.listeners }); this.touches.on('touchstart', this.handleTouchstart); this.touches.on('horizontal-swipe', this.handleHorizontalSwipe); this.touches.on('touchend', this.handleTouchend); this.touches.on('mousedown', this.handleTouchstart); this.touches.on('mouseup', this.handleTouchend); this.touches.on('tap', this.handleTap); this.initCarousel(); this.setDimensions(); this.setInitialIndex(); } ngAfterViewInit() { this.carousel.lineUpCells(); } ngOnChanges(changes) { if (changes.width || changes.height) { this.setDimensions(); this.initCarousel(); this.carousel.lineUpCells(); } } ngOnDestroy() { this.touches.destroy(); } initCarousel() { this.carousel = new Carousel({ element: this.elementRef.nativeElement.querySelector('.carousel-cells'), container: this.elementRef.nativeElement, images: this.images, cellWidth: this.getCellWidth(), overflowCellsLimit: this.overflowCellsLimit, visibleWidth: this.width, margin: this.margin, minSwipeDistance: this.minSwipeDistance, transitionDuration: this.transitionDuration, transitionTimingFunction: this.transitionTimingFunction, videoProperties: this.videoProperties }); } setDimensions() { this.hostStyleHeight = this.height + 'px'; this.hostStyleWidth = this.width + 'px'; } getFile(index) { return this.carousel.getFile(index); } handleTransitionendCellContainer(event) { this.carousel.handleSlideEnd(); } toggleVideo(video) { event.preventDefault(); if (this.videoProperties.noPlay) { return; } if (video.paused) { video.play(); this.isVideoPlaying = true; } else { video.pause(); this.isVideoPlaying = false; } this.ref.detectChanges(); } getCurrentIndex() { return this.carousel.slideCounter; } getCellWidth() { if (this._cellWidth === '100%') { return this.elementRef.nativeElement.clientWidth; } else { return this._cellWidth; } } next() { this.carousel.next(1); } prev() { this.carousel.prev(1); } select(index) { this.carousel.select(index); } isNextArrowDisabled() { return this.carousel.isNextArrowDisabled(); } isPrevArrowDisabled() { return this.carousel.isPrevArrowDisabled(); } close() { this.overlayEventService.emitChangeEvent({ type: 'Hide' }); } setInitialIndex() { if (this._properties.metadata.index != undefined) { this.select(this._properties.metadata.index); } } }; CarouselComponent.ctorParameters = () => [ { type: ElementRef }, { type: ChangeDetectorRef }, { type: EventService } ]; __decorate([ Input() ], CarouselComponent.prototype, "images", null); __decorate([ Output() ], CarouselComponent.prototype, "events", void 0); __decorate([ Input() ], CarouselComponent.prototype, "height", void 0); __decorate([ Input() ], CarouselComponent.prototype, "width", void 0); __decorate([ Input() ], CarouselComponent.prototype, "borderRadius", void 0); __decorate([ Input() ], CarouselComponent.prototype, "margin", void 0); __decorate([ Input() ], CarouselComponent.prototype, "objectFit", void 0); __decorate([ Input() ], CarouselComponent.prototype, "minSwipeDistance", void 0); __decorate([ Input() ], CarouselComponent.prototype, "transitionDuration", null); __decorate([ Input() ], CarouselComponent.prototype, "transitionTimingFunction", void 0); __decorate([ Input() ], CarouselComponent.prototype, "videoProperties", void 0); __decorate([ Input() ], CarouselComponent.prototype, "counterSeparator", void 0); __decorate([ Input() ], CarouselComponent.prototype, "overflowCellsLimit", void 0); __decorate([ Input() ], CarouselComponent.prototype, "listeners", void 0); __decorate([ Input('cellWidth') ], CarouselComponent.prototype, "cellWidth", null); __decorate([ Input('counter') ], CarouselComponent.prototype, "isCounter", null); __decorate([ Input() ], CarouselComponent.prototype, "arrows", void 0); __decorate([ Input() ], CarouselComponent.prototype, "arrowsOutside", void 0); __decorate([ Input() ], CarouselComponent.prototype, "arrowsTheme", void 0); __decorate([ Input() ], CarouselComponent.prototype, "overlayProperties", null); __decorate([ HostBinding('class.carousel') ], CarouselComponent.prototype, "hostClassCarousel", void 0); __decorate([ HostBinding('style.height') ], CarouselComponent.prototype, "hostStyleHeight", void 0); __decorate([ HostBinding('style.width') ], CarouselComponent.prototype, "hostStyleWidth", void 0); __decorate([ HostListener('window:resize', ['$event']) ], CarouselComponent.prototype, "onWindowResize", null); CarouselComponent = __decorate([ Component({ selector: 'carousel, [carousel]', exportAs: 'carousel', template: "<div class=\"carousel-backdrop\"></div>\n\n<div class=\"carousel-close\" (click)=\"close()\"></div>\n\n<div class=\"carousel-counter\" *ngIf=\"isCounter\">{{counter}}</div>\n\n<div class=\"carousel-container\" [class.carousel-moving]=\"isMoving\">\n\t<div class=\"carousel-cells\" (transitionend)=\"handleTransitionendCellContainer($event)\">\n\t\t<ng-template ngFor let-image [ngForOf]=\"images\" let-i=\"index\">\n\t\t\t<div class=\"carousel-cell\" \n\t\t\t\t*ngIf=\"i < cellLimit\" \n\t\t\t\t[style.width]=\"getCellWidth()+'px'\"\n\t\t\t\t[style.border-radius]=\"borderRadius+'px'\">\n\t\t\t\t<!-- Image -->\n\t\t\t\t<img \n\t\t\t\t\t*ngIf=\"getFile(i) && getFile(i)['image']\" \n\t\t\t\t\t[src]=\"getFile(i)['image']['path']\"\n\t\t\t\t\t[style.object-fit]=\"objectFit\"\n\t\t\t\t\tdraggable=\"false\" />\n\n\t\t\t\t<!-- Video -->\n\t\t\t\t<ng-template [ngIf]=\"getFile(i) && getFile(i)['type'] === 'video'\">\n\t\t\t\t\t<div class=\"carousel-play\" (click)=\"toggleVideo(video)\"></div>\n\n\t\t\t\t\t<video #video\n\t\t\t\t\t\t[loop]=\"videoProperties.loop\"\n\t\t\t\t\t\t[muted]=\"videoProperties.muted\"\n\t\t\t\t\t\t[controls]=\"isSafari\"\n\t\t\t\t\t\t[style.object-fit]=\"objectFit\"\n\t\t\t\t\t\t[style.border-radius]=\"borderRadius+'px'\">\n\t\t\t\t\t\t\n\t\t\t\t\t\t<source [src]=\"getFile(i)['path']\" type=\"video/mp4\">\n\t\t\t\t\t</video>\n\t\t\t\t</ng-template>\n\t\t\t</div>\n\t\t</ng-template>\n\t</div>\n</div>\n\n<div class=\"carousel-arrows\" \n\t[class.carousel-arrows-outside]=\"arrowsOutside\" \n\t[class.carousel-dark-arrows]=\"arrowsTheme === 'dark'\"\n\t*ngIf=\"arrows\">\n\t\n\t<div class=\"carousel-arrow carousel-arrow-prev\" [class.carousel-arrow-disabled]=\"isPrevArrowDisabled()\" (click)=\"prev()\"></div>\n\t<div class=\"carousel-arrow carousel-arrow-next\" [class.carousel-arrow-disabled]=\"isNextArrowDisabled()\" (click)=\"next()\"></div>\n</div>", styles: [":host{position:relative;display:block;top:0;left:0;width:100%;height:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:10000;transform-origin:top left;box-sizing:border-box}:host .carousel-container{overflow:hidden;width:100%;height:100%;cursor:-webkit-grab;cursor:grab}:host .carousel-container.carousel-moving{cursor:-webkit-grabbing;cursor:grabbing}:host .carousel-counter{text-align:right;position:absolute;z-index:30;transition:opacity .2s;top:15px;left:10px;border-radius:13px;background-color:rgba(23,37,68,.3);font-size:13px;color:#fff;padding:5px 7px;line-height:initial}:host .carousel-cells{transition:transform .2s;width:100%;height:100%;display:block}:host .carousel-cells ::ng-deep .carousel-cell.swiper-prev-image{transform:translate3d(-100%,0,0)}:host .carousel-cells ::ng-deep .carousel-cell.swiper-next-image{transform:translate3d(100%,0,0)}:host .carousel-cells ::ng-deep .carousel-cell{width:100%;height:100%;text-align:center;position:absolute;display:flex;align-items:center;justify-content:center;overflow:hidden}:host .carousel-cells ::ng-deep .carousel-cell img,:host .carousel-cells ::ng-deep .carousel-cell video{width:100%;height:100%;position:relative;-o-object-fit:contain;object-fit:contain}:host .carousel-cells ::ng-deep .carousel-cell img.swiper-hide{display:none}:host .carousel-cells ::ng-deep .carousel-cell .carousel-play{position:absolute;top:0;left:0;bottom:0;right:0;z-index:1}:host .carousel-arrow{width:40px;height:40px;background-color:#fff;background-repeat:no-repeat;background-size:31px;background-position:center;border-radius:100px;position:absolute;top:50%;margin-top:-20px;z-index:10;cursor:pointer;box-shadow:0 0 5px rgba(0,0,0,.15)}:host .carousel-arrow-prev{left:10px;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0Ij48cGF0aCBkPSJNMTUuNDEgMTYuNTlMMTAuODMgMTJsNC41OC00LjU5TDE0IDZsLTYgNiA2IDYgMS40MS0xLjQxeiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMFYweiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==)}:host .carousel-arrow-next{right:10px;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0Ij48cGF0aCBkPSJNOC41OSAxNi41OUwxMy4xNyAxMiA4LjU5IDcuNDEgMTAgNmw2IDYtNiA2LTEuNDEtMS40MXoiLz48cGF0aCBkPSJNMCAwaDI0djI0SDBWMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=)}:host .carousel-arrows-outside .carousel-arrow-prev{left:-60px}:host .carousel-arrows-outside .carousel-arrow-next{right:-60px}:host .carousel-dark-arrows .carousel-arrow{-webkit-filter:invert(1);filter:invert(1)}:host .carousel-arrow-disabled{cursor:default;opacity:.5}:host .carousel-close{position:fixed;top:10px;right:10px;width:40px;height:40px;z-index:100;cursor:pointer;background-repeat:no-repeat;background-size:31px;background-position:center;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0Ij48cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=);-webkit-filter:invert(1);filter:invert(1)}:host .carousel-backdrop{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#000;opacity:.5}"] }) ], CarouselComponent); let AdDirective = class AdDirective { constructor(viewContainerRef) { this.viewContainerRef = viewContainerRef; } }; AdDirective.ctorParameters = () => [ { type: ViewContainerRef } ]; AdDirective = __decorate([ Directive({ selector: '[ad-host]', }) ], AdDirective); let OverlayContainerComponent = class OverlayContainerComponent { constructor(componentFactoryResolver, elementRef, eventService) { this.componentFactoryResolver = componentFactoryResolver; this.elementRef = elementRef; this.eventService = eventService; this.overlayBackdrop = true; this.minTimeout = 30; this._hostOpacity = 0; this.globalEventsSubscription = this.eventService.emitter.subscribe((event) => { this.handleGlobalEvents(event); }); } get hostOpacity() { return this.properties.fadeIn ? this._hostOpacity : 1; } set hostOpacity(value) { this._hostOpacity = value; } get hostTransition() { const duration = this.properties.animationDuration + 'ms '; const esing = this.properties.animationTimingFunction; return 'opacity ' + duration + esing + ', transform ' + duration + esing; } get hostZIndex() { return this.properties.zIndex; } get hostWidth() { return this.properties.wrapperWidth; } get hostHeight() { return this.properties.wrapperHeight; } get hostPosition() { return this.properties.position; } onClick(event) { if (!this.elementRef.nativeElement.contains(event.target)) { if (this.hostShown) { this.closeOverlay(); } } } transitionEnd(event) { if (event.target.tagName.toLowerCase() != "overlay") { return; } if (event.propertyName != "opacity") { return; } if (this.hostShown) { this.closeOverlayEnd(); //this.stateEvents.emit("shown"); } else { this.hostShown = true; //this.stateEvents.emit("hidden"); } } get popoverClass() { if (this.properties.metadata) { return this.properties.metadata.popoverClass; } } ngOnInit() { this.loadComponent(); this.initialOverlay(); setTimeout(() => { this.isInitial = true; }, this.minTimeout); // Note: not good } ngAfterViewInit() { setTimeout(() => { this.showOverlayAnimation(); }, this.minTimeout); } ngOnDestroy() { if (this.globalEventsSubscription) { this.globalEventsSubscription.unsubscribe(); } } initialOverlay() { this.hostTransform = 'translateY(' + this.properties.animationTranslateY + ')'; } showOverlayAnimation() { this.hostOpacity = 1; this.hostTransform = 'translateY(0px)'; } loadComponent() { let adItem = this.properties; let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.mainComponent); let viewContainerRef = this.adHost.viewContainerRef; viewContainerRef.clear(); let componentRef = viewContainerRef.createComponent(componentFactory); let componentRefElement = componentRef.location.nativeElement; // Set styles componentRefElement.style.width = this.properties.width; componentRefElement.style.height = this.properties.height; // Set classes if (typeof this.popoverClass === 'string') { componentRefElement.classList.add(this.popoverClass); } if (typeof this.popoverClass === 'object') { this.popoverClass.forEach(function (className) { componentRefElement.classList.add(className); }); } // Pass properties componentRef.instance.overlayProperties = this.properties; } closeOverlay() { this.hostOpacity = 0; this.hostTransform = 'translateY(' + this.properties.animationTranslateY + ')'; } closeOverlayEnd() { this.hostShown = false; this.eventService.emitChangeEvent({ type: '[Overlay] Hide' }); } handleGlobalEvents(event) { if (event.type === 'Hide') { this.closeOverlay(); } } }; OverlayContainerComponent.ctorParameters = () => [ { type: ComponentFactoryResolver }, { type: ElementRef }, { type: EventService } ]; __decorate([ ViewChild(AdDirective, { static: true }) ], OverlayContainerComponent.prototype, "adHost", void 0); __decorate([ Input() ], OverlayContainerComponent.prototype, "properties", void 0); __decorate([ HostBinding('style.opacity') ], OverlayContainerComponent.prototype, "hostOpacity", null); __decorate([ HostBinding('style.transition') ], OverlayContainerComponent.prototype, "hostTransition", null); __decorate([ HostBinding('style.transform') ], OverlayContainerComponent.prototype, "hostTransform", void 0); __decorate([ HostBinding('style.z-index') ], OverlayContainerComponent.prototype, "hostZIndex", null); __decorate([ HostBinding('style.width') ], OverlayContainerComponent.prototype, "hostWidth", null); __decorate([ HostBinding('style.height') ], OverlayContainerComponent.prototype, "hostHeight", null); __decorate([ HostBinding('style.position') ], OverlayContainerComponent.prototype, "hostPosition", null); __decorate([ HostBinding('class.overlay-shown') ], OverlayContainerComponent.prototype, "hostShown", void 0); __decorate([ HostListener('document:click', ['$event']) ], OverlayContainerComponent.prototype, "onClick", null); __decorate([ HostListener('transitionend', ['$event']) ], OverlayContainerComponent.prototype, "transitionEnd", null); OverlayContainerComponent = __decorate([ Component({ selector: 'overlay', template: "<!--\n<div class=\"overlay-backdrop\" \n\t*ngIf=\"properties.overlayBackdrop\" \n\t(click)=\"onBackdropClick()\" \n\t[ngClass]=\"properties.backdropClass\"></div>\n-->\n<!--\n<div class=\"overlay-container\"\n\t[ngStyle]=\"containerStyles\" \n\t[ngClass]=\"properties.overlayClass\">\n\n\t<ng-template ad-host></ng-template>\n</div>\n-->\n