@ngu/carousel
Version:
Angular Universal carousel
723 lines • 117 kB
JavaScript
import { isPlatformBrowser } from '@angular/common';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, ElementRef, EventEmitter, Inject, Input, isDevMode, IterableDiffers, Output, PLATFORM_ID, Renderer2, ViewChild } from '@angular/core';
import { EMPTY, fromEvent, interval, merge, Observable, of, Subject } from 'rxjs';
import { mapTo, startWith, switchMap, takeUntil } from 'rxjs/operators';
import { NguCarouselDefDirective, NguCarouselNextDirective, NguCarouselOutlet, NguCarouselPrevDirective } from './../ngu-carousel.directive';
import { Breakpoints, NguCarouselOutletContext, NguCarouselStore } from './ngu-carousel';
// @dynamic
// @dynamic
// tslint:disable-next-line:component-class-suffix
export class NguCarousel extends NguCarouselStore {
constructor(_el, _renderer, _differs, platformId, cdr) {
super();
this._el = _el;
this._renderer = _renderer;
this._differs = _differs;
this.platformId = platformId;
this.cdr = cdr;
this.withAnim = true;
this.isHovered = false;
this.carouselLoad = new EventEmitter();
// tslint:disable-next-line:no-output-on-prefix
this.onMove = new EventEmitter();
this._intervalController$ = new Subject();
this.pointNumbers = [];
}
get dataSource() {
return this._dataSource;
}
set dataSource(data) {
if (data) {
this._switchDataSource(data);
}
}
/** The setter is used to catch the button if the button has ngIf
* issue id #91
*/
set nextBtn(btn) {
this.listener2 && this.listener2();
if (btn) {
this.listener2 = this._renderer.listen(btn.nativeElement, 'click', () => this._carouselScrollOne(1));
}
}
/** The setter is used to catch the button if the button has ngIf
* issue id #91
*/
set prevBtn(btn) {
this.listener1 && this.listener1();
if (btn) {
this.listener1 = this._renderer.listen(btn.nativeElement, 'click', () => this._carouselScrollOne(0));
}
}
/**
* Tracking function that will be used to check the differences in data changes. Used similarly
* to `ngFor` `trackBy` function. Optimize Items operations by identifying a Items based on its data
* relative to the function to know if a Items should be added/removed/moved.
* Accepts a function that takes two parameters, `index` and `item`.
*/
get trackBy() {
return this._trackByFn;
}
set trackBy(fn) {
if (isDevMode() && fn != null && typeof fn !== 'function' && console && console.warn) {
console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}.`);
}
this._trackByFn = fn;
}
ngOnInit() {
this._dataDiffer = this._differs.find([]).create((_i, item) => {
return this.trackBy ? this.trackBy(item.dataIndex, item.data) : item;
});
}
ngDoCheck() {
this.arrayChanges = this._dataDiffer.diff(this.dataSource);
if (this.arrayChanges && this._defDirec) {
this._observeRenderChanges();
}
}
_switchDataSource(dataSource) {
this._dataSource = dataSource;
if (this._defDirec) {
this._observeRenderChanges();
}
}
_observeRenderChanges() {
let dataStream;
if (this._dataSource instanceof Observable) {
dataStream = this._dataSource;
}
else if (Array.isArray(this._dataSource)) {
dataStream = of(this._dataSource);
}
if (dataStream) {
this._dataSubscription = dataStream
.pipe(takeUntil(this._intervalController$))
.subscribe(data => {
this.renderNodeChanges(data);
this.isLast = false;
});
}
}
renderNodeChanges(data, viewContainer = this._nodeOutlet.viewContainer) {
if (!this.arrayChanges)
return;
this.arrayChanges.forEachOperation((item, adjustedPreviousIndex, currentIndex) => {
const node = this._getNodeDef(data[currentIndex], currentIndex);
if (item.previousIndex == null) {
const context = new NguCarouselOutletContext(data[currentIndex]);
context.index = currentIndex;
viewContainer.createEmbeddedView(node.template, context, currentIndex);
}
else if (currentIndex == null) {
viewContainer.remove(adjustedPreviousIndex);
}
else {
const view = viewContainer.get(adjustedPreviousIndex);
viewContainer.move(view, currentIndex);
}
});
this._updateItemIndexContext();
if (this.carousel) {
this._storeCarouselData();
}
}
/**
* Updates the index-related context for each row to reflect any changes in the index of the rows,
* e.g. first/last/even/odd.
*/
_updateItemIndexContext() {
const viewContainer = this._nodeOutlet.viewContainer;
for (let renderIndex = 0, count = viewContainer.length; renderIndex < count; renderIndex++) {
const viewRef = viewContainer.get(renderIndex);
const context = viewRef.context;
context.count = count;
context.first = renderIndex === 0;
context.last = renderIndex === count - 1;
context.even = renderIndex % 2 === 0;
context.odd = !context.even;
context.index = renderIndex;
}
}
_getNodeDef(data, i) {
if (this._defDirec.length === 1) {
return this._defDirec.first;
}
const nodeDef = this._defDirec.find(def => def.when && def.when(i, data)) || this._defaultNodeDef;
return nodeDef;
}
ngAfterViewInit() {
this.carousel = this._el.nativeElement;
this._inputValidation();
this.carouselCssNode = this._createStyleElem();
if (isPlatformBrowser(this.platformId)) {
this._carouselInterval();
if (!this.vertical.enabled) {
this._touch();
}
this.listener3 = this._renderer.listen('window', 'resize', event => {
this._onResizing(event);
});
this._onWindowScrolling();
}
}
ngAfterContentInit() {
this._observeRenderChanges();
this.cdr.markForCheck();
}
_inputValidation() {
this.inputs.gridBreakpoints = this.inputs.gridBreakpoints ? this.inputs.gridBreakpoints : new Breakpoints();
if (this.inputs.grid.xl === undefined) {
this.inputs.grid.xl = this.inputs.grid.lg;
}
this.type = this.inputs.grid.all !== 0 ? 'fixed' : 'responsive';
this.loop = this.inputs.loop || false;
this.inputs.easing = this.inputs.easing || 'cubic-bezier(0, 0, 0.2, 1)';
this.touch.active = this.inputs.touch || false;
this.RTL = this.inputs.RTL ? true : false;
this.interval = this.inputs.interval || null;
this.velocity = typeof this.inputs.velocity === 'number' ? this.inputs.velocity : this.velocity;
if (this.inputs.vertical && this.inputs.vertical.enabled) {
this.vertical.enabled = this.inputs.vertical.enabled;
this.vertical.height = this.inputs.vertical.height;
}
this.directionSym = this.RTL ? '' : '-';
this.point =
this.inputs.point && typeof this.inputs.point.visible !== 'undefined'
? this.inputs.point.visible
: true;
this._carouselSize();
}
ngOnDestroy() {
this.carouselInt && this.carouselInt.unsubscribe();
this._intervalController$.unsubscribe();
this.carouselLoad.complete();
this.onMove.complete();
/** remove listeners */
clearTimeout(this.onScrolling);
for (let i = 1; i <= 4; i++) {
const str = `listener${i}`;
this[str] && this[str]();
}
}
_onResizing(event) {
clearTimeout(this.onResize);
this.onResize = setTimeout(() => {
if (this.deviceWidth !== event.target.outerWidth) {
this._setStyle(this.nguItemsContainer.nativeElement, 'transition', ``);
this._storeCarouselData();
}
}, 500);
}
/** Get Touch input */
_touch() {
if (this.inputs.touch) {
import('hammerjs').then(() => {
const hammertime = new Hammer(this.touchContainer.nativeElement);
hammertime.get('pan').set({ direction: Hammer.DIRECTION_HORIZONTAL });
hammertime.on('panstart', (ev) => {
this.carouselWidth = this.nguItemsContainer.nativeElement.offsetWidth;
this.touchTransform = this.transform[this.deviceType];
this.dexVal = 0;
this._setStyle(this.nguItemsContainer.nativeElement, 'transition', '');
});
if (this.vertical.enabled) {
hammertime.on('panup', (ev) => {
this._touchHandling('panleft', ev);
});
hammertime.on('pandown', (ev) => {
this._touchHandling('panright', ev);
});
}
else {
hammertime.on('panleft', (ev) => {
this._touchHandling('panleft', ev);
});
hammertime.on('panright', (ev) => {
this._touchHandling('panright', ev);
});
}
hammertime.on('panend pancancel', (ev) => {
if (Math.abs(ev.velocity) >= this.velocity) {
this.touch.velocity = ev.velocity;
let direc = 0;
if (!this.RTL) {
direc = this.touch.swipe === 'panright' ? 0 : 1;
}
else {
direc = this.touch.swipe === 'panright' ? 1 : 0;
}
this._carouselScrollOne(direc);
}
else {
this.dexVal = 0;
this._setStyle(this.nguItemsContainer.nativeElement, 'transition', 'transform 324ms cubic-bezier(0, 0, 0.2, 1)');
this._setStyle(this.nguItemsContainer.nativeElement, 'transform', '');
}
});
hammertime.on('hammer.input', ev => {
// allow nested touch events to no propagate, this may have other side affects but works for now.
// TODO: It is probably better to check the source element of the event and only apply the handle to the correct carousel
ev.srcEvent.stopPropagation();
});
});
}
}
/** handle touch input */
_touchHandling(e, ev) {
// vertical touch events seem to cause to panstart event with an odd delta
// and a center of {x:0,y:0} so this will ignore them
if (ev.center.x === 0) {
return;
}
ev = Math.abs(this.vertical.enabled ? ev.deltaY : ev.deltaX);
let valt = ev - this.dexVal;
valt =
this.type === 'responsive'
? (Math.abs(ev - this.dexVal) /
(this.vertical.enabled ? this.vertical.height : this.carouselWidth)) *
100
: valt;
this.dexVal = ev;
this.touch.swipe = e;
this._setTouchTransfrom(e, valt);
this._setTransformFromTouch();
}
_setTouchTransfrom(e, valt) {
const condition = this.RTL ? 'panright' : 'panleft';
this.touchTransform = e === condition ? valt + this.touchTransform : this.touchTransform - valt;
}
_setTransformFromTouch() {
if (this.touchTransform < 0) {
this.touchTransform = 0;
}
const type = this.type === 'responsive' ? '%' : 'px';
this._setStyle(this.nguItemsContainer.nativeElement, 'transform', this.vertical.enabled
? `translate3d(0, ${this.directionSym}${this.touchTransform}${type}, 0)`
: `translate3d(${this.directionSym}${this.touchTransform}${type}, 0, 0)`);
}
/** this fn used to disable the interval when it is not on the viewport */
_onWindowScrolling() {
const top = this.carousel.offsetTop;
const scrollY = window.scrollY;
const heightt = window.innerHeight;
const carouselHeight = this.carousel.offsetHeight;
const isCarouselOnScreen = top <= scrollY + heightt - carouselHeight / 4 && top + carouselHeight / 2 >= scrollY;
if (isCarouselOnScreen) {
this._intervalController$.next(1);
}
else {
this._intervalController$.next(0);
}
}
/** store data based on width of the screen for the carousel */
_storeCarouselData() {
const breakpoints = this.inputs.gridBreakpoints;
this.deviceWidth = isPlatformBrowser(this.platformId) ? window.innerWidth : breakpoints.xl;
this.carouselWidth = this.carouselMain1.nativeElement.offsetWidth;
if (this.type === 'responsive') {
this.deviceType =
this.deviceWidth >= breakpoints.xl
? 'xl'
: this.deviceWidth >= breakpoints.lg
? 'lg'
: this.deviceWidth >= breakpoints.md
? 'md'
: this.deviceWidth >= breakpoints.sm
? 'sm'
: 'xs';
this.items = this.inputs.grid[this.deviceType];
this.itemWidth = this.carouselWidth / this.items;
}
else {
this.items = Math.trunc(this.carouselWidth / this.inputs.grid.all);
this.itemWidth = this.inputs.grid.all;
this.deviceType = 'all';
}
this.slideItems = +(this.inputs.slide < this.items ? this.inputs.slide : this.items);
this.load = this.inputs.load >= this.slideItems ? this.inputs.load : this.slideItems;
this.speed = this.inputs.speed && this.inputs.speed > -1 ? this.inputs.speed : 400;
this._carouselPoint();
}
/** Used to reset the carousel */
reset(withOutAnimation) {
withOutAnimation && (this.withAnim = false);
this.carouselCssNode.innerHTML = '';
this.moveTo(0);
this._carouselPoint();
}
/** Init carousel point */
_carouselPoint() {
const Nos = this.dataSource.length - (this.items - this.slideItems);
this.pointIndex = Math.ceil(Nos / this.slideItems);
const pointers = [];
if (this.pointIndex > 1 || !this.inputs.point.hideOnSingleSlide) {
for (let i = 0; i < this.pointIndex; i++) {
pointers.push(i);
}
}
this.pointNumbers = pointers;
this._carouselPointActiver();
if (this.pointIndex <= 1) {
this._btnBoolean(1, 1);
}
else {
if (this.currentSlide === 0 && !this.loop) {
this._btnBoolean(1, 0);
}
else {
this._btnBoolean(0, 0);
}
}
}
/** change the active point in carousel */
_carouselPointActiver() {
const i = Math.ceil(this.currentSlide / this.slideItems);
this.activePoint = i;
this.cdr.markForCheck();
}
/** this function is used to scoll the carousel when point is clicked */
moveTo(slide, withOutAnimation) {
// slide = slide - 1;
withOutAnimation && (this.withAnim = false);
if (this.activePoint !== slide && slide < this.pointIndex) {
let slideremains;
const btns = this.currentSlide < slide ? 1 : 0;
switch (slide) {
case 0:
this._btnBoolean(1, 0);
slideremains = slide * this.slideItems;
break;
case this.pointIndex - 1:
this._btnBoolean(0, 1);
slideremains = this.dataSource.length - this.items;
break;
default:
this._btnBoolean(0, 0);
slideremains = slide * this.slideItems;
}
this._carouselScrollTwo(btns, slideremains, this.speed);
}
}
/** set the style of the carousel based the inputs data */
_carouselSize() {
this.token = this._generateID();
let dism = '';
this.styleid = `.${this.token} > .ngucarousel > .ngu-touch-container > .ngucarousel-items`;
if (this.inputs.custom === 'banner') {
this._renderer.addClass(this.carousel, 'banner');
}
if (this.inputs.animation === 'lazy') {
dism += `${this.styleid} > .item {transition: transform .6s ease;}`;
}
const breakpoints = this.inputs.gridBreakpoints;
let itemStyle = '';
if (this.vertical.enabled) {
const itemWidthXS = `${this.styleid} > .item {height: ${this.vertical.height /
+this.inputs.grid.xs}px}`;
const itemWidthSM = `${this.styleid} > .item {height: ${this.vertical.height /
+this.inputs.grid.sm}px}`;
const itemWidthMD = `${this.styleid} > .item {height: ${this.vertical.height /
+this.inputs.grid.md}px}`;
const itemWidthLG = `${this.styleid} > .item {height: ${this.vertical.height /
+this.inputs.grid.lg}px}`;
const itemWidthXL = `${this.styleid} > .item {height: ${this.vertical.height /
+this.inputs.grid.xl}px}`;
itemStyle = `@media (max-width:${breakpoints.sm - 1}px){${itemWidthXS}}
@media (max-width:${breakpoints.sm}px){${itemWidthSM}}
@media (min-width:${breakpoints.md}px){${itemWidthMD}}
@media (min-width:${breakpoints.lg}px){${itemWidthLG}}
@media (min-width:${breakpoints.xl}px){${itemWidthXL}}`;
}
else if (this.type === 'responsive') {
const itemWidthXS = this.inputs.type === 'mobile'
? `${this.styleid} .item {flex: 0 0 ${95 / +this.inputs.grid.xs}%; width: ${95 /
+this.inputs.grid.xs}%;}`
: `${this.styleid} .item {flex: 0 0 ${100 / +this.inputs.grid.xs}%; width: ${100 /
+this.inputs.grid.xs}%;}`;
const itemWidthSM = `${this.styleid} > .item {flex: 0 0 ${100 /
+this.inputs.grid.sm}%; width: ${100 / +this.inputs.grid.sm}%}`;
const itemWidthMD = `${this.styleid} > .item {flex: 0 0 ${100 /
+this.inputs.grid.md}%; width: ${100 / +this.inputs.grid.md}%}`;
const itemWidthLG = `${this.styleid} > .item {flex: 0 0 ${100 /
+this.inputs.grid.lg}%; width: ${100 / +this.inputs.grid.lg}%}`;
const itemWidthXL = `${this.styleid} > .item {flex: 0 0 ${100 /
+this.inputs.grid.xl}%; width: ${100 / +this.inputs.grid.xl}%}`;
itemStyle = `@media (max-width:${breakpoints.sm - 1}px){${itemWidthXS}}
@media (min-width:${breakpoints.sm}px){${itemWidthSM}}
@media (min-width:${breakpoints.md}px){${itemWidthMD}}
@media (min-width:${breakpoints.lg}px){${itemWidthLG}}
@media (min-width:${breakpoints.xl}px){${itemWidthXL}}`;
}
else {
itemStyle = `${this.styleid} .item {flex: 0 0 ${this.inputs.grid.all}px; width: ${this.inputs.grid.all}px;}`;
}
this._renderer.addClass(this.carousel, this.token);
if (this.vertical.enabled) {
this._renderer.addClass(this.nguItemsContainer.nativeElement, 'nguvertical');
this._renderer.setStyle(this.carouselMain1.nativeElement, 'height', `${this.vertical.height}px`);
}
// tslint:disable-next-line:no-unused-expression
this.RTL && !this.vertical.enabled && this._renderer.addClass(this.carousel, 'ngurtl');
this._createStyleElem(`${dism} ${itemStyle}`);
this._storeCarouselData();
}
/** logic to scroll the carousel step 1 */
_carouselScrollOne(Btn) {
let itemSpeed = this.speed;
let translateXval = 0;
let currentSlide = 0;
const touchMove = Math.ceil(this.dexVal / this.itemWidth);
this._setStyle(this.nguItemsContainer.nativeElement, 'transform', '');
if (this.pointIndex === 1) {
return;
}
else if (Btn === 0 && ((!this.loop && !this.isFirst) || this.loop)) {
const currentSlideD = this.currentSlide - this.slideItems;
const MoveSlide = currentSlideD + this.slideItems;
this._btnBoolean(0, 1);
if (this.currentSlide === 0) {
currentSlide = this.dataSource.length - this.items;
itemSpeed = 400;
this._btnBoolean(0, 1);
}
else if (this.slideItems >= MoveSlide) {
currentSlide = translateXval = 0;
this._btnBoolean(1, 0);
}
else {
this._btnBoolean(0, 0);
if (touchMove > this.slideItems) {
currentSlide = this.currentSlide - touchMove;
itemSpeed = 200;
}
else {
currentSlide = this.currentSlide - this.slideItems;
}
}
this._carouselScrollTwo(Btn, currentSlide, itemSpeed);
}
else if (Btn === 1 && ((!this.loop && !this.isLast) || this.loop)) {
if (this.dataSource.length <= this.currentSlide + this.items + this.slideItems &&
!this.isLast) {
currentSlide = this.dataSource.length - this.items;
this._btnBoolean(0, 1);
}
else if (this.isLast) {
currentSlide = translateXval = 0;
itemSpeed = 400;
this._btnBoolean(1, 0);
}
else {
this._btnBoolean(0, 0);
if (touchMove > this.slideItems) {
currentSlide = this.currentSlide + this.slideItems + (touchMove - this.slideItems);
itemSpeed = 200;
}
else {
currentSlide = this.currentSlide + this.slideItems;
}
}
this._carouselScrollTwo(Btn, currentSlide, itemSpeed);
}
}
/** logic to scroll the carousel step 2 */
_carouselScrollTwo(Btn, currentSlide, itemSpeed) {
// tslint:disable-next-line:no-unused-expression
if (this.dexVal !== 0) {
const val = Math.abs(this.touch.velocity);
let somt = Math.floor((this.dexVal / val / this.dexVal) * (this.deviceWidth - this.dexVal));
somt = somt > itemSpeed ? itemSpeed : somt;
itemSpeed = somt < 200 ? 200 : somt;
this.dexVal = 0;
}
if (this.withAnim) {
this._setStyle(this.nguItemsContainer.nativeElement, 'transition', `transform ${itemSpeed}ms ${this.inputs.easing}`);
this.inputs.animation &&
this._carouselAnimator(Btn, currentSlide + 1, currentSlide + this.items, itemSpeed, Math.abs(this.currentSlide - currentSlide));
}
else {
this._setStyle(this.nguItemsContainer.nativeElement, 'transition', ``);
}
this.itemLength = this.dataSource.length;
this._transformStyle(currentSlide);
this.currentSlide = currentSlide;
this.onMove.emit(this);
this._carouselPointActiver();
this._carouselLoadTrigger();
this.withAnim = true;
}
/** boolean function for making isFirst and isLast */
_btnBoolean(first, last) {
this.isFirst = !!first;
this.isLast = !!last;
}
_transformString(grid, slide) {
let collect = '';
collect += `${this.styleid} { transform: translate3d(`;
if (this.vertical.enabled) {
this.transform[grid] = (this.vertical.height / this.inputs.grid[grid]) * slide;
collect += `0, -${this.transform[grid]}px, 0`;
}
else {
this.transform[grid] = (100 / this.inputs.grid[grid]) * slide;
collect += `${this.directionSym}${this.transform[grid]}%, 0, 0`;
}
collect += `); }`;
return collect;
}
/** set the transform style to scroll the carousel */
_transformStyle(slide) {
let slideCss = '';
if (this.type === 'responsive') {
const breakpoints = this.inputs.gridBreakpoints;
slideCss = `@media (max-width: ${breakpoints.sm - 1}px) {${this._transformString('xs', slide)}}
@media (min-width: ${breakpoints.sm}px) {${this._transformString('sm', slide)} }
@media (min-width: ${breakpoints.md}px) {${this._transformString('md', slide)} }
@media (min-width: ${breakpoints.lg}px) {${this._transformString('lg', slide)} }
@media (min-width: ${breakpoints.xl}px) {${this._transformString('xl', slide)} }`;
}
else {
this.transform.all = this.inputs.grid.all * slide;
slideCss = `${this.styleid} { transform: translate3d(${this.directionSym}${this.transform.all}px, 0, 0);`;
}
this.carouselCssNode.textContent = slideCss;
}
/** this will trigger the carousel to load the items */
_carouselLoadTrigger() {
if (typeof this.inputs.load === 'number') {
this.dataSource.length - this.load <= this.currentSlide + this.items &&
this.carouselLoad.emit(this.currentSlide);
}
}
/** generate Class for each carousel to set specific style */
_generateID() {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 6; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return `ngucarousel${text}`;
}
/** handle the auto slide */
_carouselInterval() {
const container = this.carouselMain1.nativeElement;
if (this.interval && this.loop) {
this.listener4 = this._renderer.listen('window', 'scroll', () => {
clearTimeout(this.onScrolling);
this.onScrolling = setTimeout(() => {
this._onWindowScrolling();
}, 600);
});
const play$ = fromEvent(container, 'mouseleave').pipe(mapTo(1));
const pause$ = fromEvent(container, 'mouseenter').pipe(mapTo(0));
const touchPlay$ = fromEvent(container, 'touchstart').pipe(mapTo(1));
const touchPause$ = fromEvent(container, 'touchend').pipe(mapTo(0));
const interval$ = interval(this.inputs.interval.timing).pipe(mapTo(1));
setTimeout(() => {
this.carouselInt = merge(play$, touchPlay$, pause$, touchPause$, this._intervalController$)
.pipe(startWith(1), switchMap(val => {
this.isHovered = !val;
this.cdr.markForCheck();
return val ? interval$ : EMPTY;
}))
.subscribe(res => {
this._carouselScrollOne(1);
});
}, this.interval.initialDelay);
}
}
_updateItemIndexContextAni() {
const viewContainer = this._nodeOutlet.viewContainer;
for (let renderIndex = 0, count = viewContainer.length; renderIndex < count; renderIndex++) {
const viewRef = viewContainer.get(renderIndex);
const context = viewRef.context;
context.count = count;
context.first = renderIndex === 0;
context.last = renderIndex === count - 1;
context.even = renderIndex % 2 === 0;
context.odd = !context.even;
context.index = renderIndex;
}
}
/** animate the carousel items */
_carouselAnimator(direction, start, end, speed, length, viewContainer = this._nodeOutlet.viewContainer) {
let val = length < 5 ? length : 5;
val = val === 1 ? 3 : val;
const collectIndex = [];
if (direction === 1) {
for (let i = start - 1; i < end; i++) {
collectIndex.push(i);
val = val * 2;
const viewRef = viewContainer.get(i);
const context = viewRef.context;
context.animate = { value: true, params: { distance: val } };
}
}
else {
for (let i = end - 1; i >= start - 1; i--) {
collectIndex.push(i);
val = val * 2;
const viewRef = viewContainer.get(i);
const context = viewRef.context;
context.animate = { value: true, params: { distance: -val } };
}
}
this.cdr.markForCheck();
setTimeout(() => {
this._removeAnimations(collectIndex);
}, speed * 0.7);
}
_removeAnimations(indexs) {
const viewContainer = this._nodeOutlet.viewContainer;
indexs.forEach(i => {
const viewRef = viewContainer.get(i);
const context = viewRef.context;
context.animate = { value: false, params: { distance: 0 } };
});
this.cdr.markForCheck();
}
/** Short form for setElementStyle */
_setStyle(el, prop, val) {
this._renderer.setStyle(el, prop, val);
}
/** For generating style tag */
_createStyleElem(datas) {
const styleItem = this._renderer.createElement('style');
if (datas) {
const styleText = this._renderer.createText(datas);
this._renderer.appendChild(styleItem, styleText);
}
this._renderer.appendChild(this.carousel, styleItem);
return styleItem;
}
}
NguCarousel.decorators = [
{ type: Component, args: [{
selector: 'ngu-carousel',
template: "<div #ngucarousel class=\"ngucarousel\">\r\n <div #touchContainer class=\"ngu-touch-container\">\r\n <div #nguItemsContainer class=\"ngucarousel-items\">\r\n <ng-container nguCarouselOutlet></ng-container>\r\n </div>\r\n </div>\r\n <div class=\"nguclearFix\"></div>\r\n <ng-content select=\"[NguCarouselPrev]\"></ng-content>\r\n <ng-content select=\"[NguCarouselNext]\"></ng-content>\r\n</div>\r\n<ng-content select=\"[NguCarouselPoint]\"></ng-content>\r\n",
changeDetection: ChangeDetectionStrategy.OnPush,
styles: [":host{display:block;position:relative}:host.ngurtl{direction:rtl}.ngucarousel{height:100%;overflow:hidden;position:relative}.ngucarousel .ngucarousel-items{display:flex;height:100%;position:relative}.nguvertical{flex-direction:column}.banner .ngucarouselPointDefault .ngucarouselPoint{bottom:20px;position:absolute;width:100%}.banner .ngucarouselPointDefault .ngucarouselPoint li{background:hsla(0,0%,100%,.55)}.banner .ngucarouselPointDefault .ngucarouselPoint li.active{background:#fff}.banner .ngucarouselPointDefault .ngucarouselPoint li:hover{cursor:pointer}.ngucarouselPointDefault .ngucarouselPoint{box-sizing:border-box;list-style-type:none;margin:0;overflow:auto;padding:12px;text-align:center;white-space:nowrap}.ngucarouselPointDefault .ngucarouselPoint li{background:rgba(0,0,0,.55);border-radius:50%;display:inline-block;margin:0 4px;padding:4px;transition:.4s;transition-timing-function:cubic-bezier(.17,.67,.83,.67)}.ngucarouselPointDefault .ngucarouselPoint li.active{background:#6b6b6b;transform:scale(1.8)}.ngucarouselPointDefault .ngucarouselPoint li:hover{cursor:pointer}.nguclearFix{clear:both}"]
},] }
];
NguCarousel.ctorParameters = () => [
{ type: ElementRef },
{ type: Renderer2 },
{ type: IterableDiffers },
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] },
{ type: ChangeDetectorRef }
];
NguCarousel.propDecorators = {
inputs: [{ type: Input }],
carouselLoad: [{ type: Output }],
onMove: [{ type: Output }],
dataSource: [{ type: Input, args: ['dataSource',] }],
_defDirec: [{ type: ContentChildren, args: [NguCarouselDefDirective,] }],
_nodeOutlet: [{ type: ViewChild, args: [NguCarouselOutlet, { static: true },] }],
nextBtn: [{ type: ContentChild, args: [NguCarouselNextDirective, /* TODO: add static flag */ { read: ElementRef },] }],
prevBtn: [{ type: ContentChild, args: [NguCarouselPrevDirective, /* TODO: add static flag */ { read: ElementRef },] }],
carouselMain1: [{ type: ViewChild, args: ['ngucarousel', { read: ElementRef, static: true },] }],
nguItemsContainer: [{ type: ViewChild, args: ['nguItemsContainer', { read: ElementRef, static: true },] }],
touchContainer: [{ type: ViewChild, args: ['touchContainer', { read: ElementRef, static: true },] }],
trackBy: [{ type: Input }]
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd1LWNhcm91c2VsLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25ndS1jYXJvdXNlbC9zcmMvbGliL25ndS1jYXJvdXNlbC9uZ3UtY2Fyb3VzZWwuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXBELE9BQU8sRUFHTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osZUFBZSxFQUVmLFVBQVUsRUFDVixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxTQUFTLEVBSVQsZUFBZSxFQUdmLE1BQU0sRUFDTixXQUFXLEVBRVgsU0FBUyxFQUVULFNBQVMsRUFFVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUNoRyxPQUFPLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEUsT0FBTyxFQUNMLHVCQUF1QixFQUN2Qix3QkFBd0IsRUFDeEIsaUJBQWlCLEVBQ2pCLHdCQUF3QixFQUN6QixNQUFNLDZCQUE2QixDQUFDO0FBQ3JDLE9BQU8sRUFBRSxXQUFXLEVBQXFCLHdCQUF3QixFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFNUcsV0FBVztBQU9YLFdBQVc7QUFDWCxrREFBa0Q7QUFDbEQsTUFBTSxPQUFPLFdBQWUsU0FBUSxnQkFBZ0I7SUEyR2xELFlBQ1UsR0FBZSxFQUNmLFNBQW9CLEVBQ3BCLFFBQXlCLEVBQ0osVUFBa0IsRUFDdkMsR0FBc0I7UUFFOUIsS0FBSyxFQUFFLENBQUM7UUFO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