From d1e1506019be411070f8142ee49c37f906dff376 Mon Sep 17 00:00:00 2001 From: Sheik Althaf Date: Sun, 4 Mar 2018 17:38:54 +0530 Subject: [PATCH] vertical carousel is added and restructure the carousel with flex box --- README.md | 192 ++++++++--- package.json | 61 ++-- src/ngu-carousel/ngu-carousel.component.ts | 366 ++++++++++++--------- src/ngu-carousel/ngu-carousel.interface.ts | 19 +- 4 files changed, 409 insertions(+), 229 deletions(-) diff --git a/README.md b/README.md index 817ac8ce..5af5a78a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ for ChangeLog go to [CHANGELOG.md](https://github.com/sheikalthaf/ngu-carousel/b ## Demo -Demo available [Here](https://sheikalthaf.github.io/ngu-carousel) +Demo available [Here](https://sheikalthaf.github.io/ngx-carousel) ## Installation @@ -22,11 +22,9 @@ Include CarouselModule in your app module: import { NguCarouselModule } from '@ngu/carousel'; @NgModule({ - imports: [ - NguCarouselModule - ], + imports: [NguCarouselModule] }) -export class AppModule { } +export class AppModule {} ``` Now ngu-carousel supports touch with the help of hammerjs @@ -37,7 +35,6 @@ Import hammerjs in `polyfills.ts` file ```javascript import 'hammerjs'; - ``` Then use in your component: @@ -99,7 +96,6 @@ export class SampleComponent implements OnInit { ## Input Interface ```javascript - export class NguCarouselStore { type: string; deviceType: DeviceType; @@ -125,6 +121,7 @@ export class NguCarouselStore { isFirst: boolean; isLast: boolean; RTL: boolean; + vertical: Vertical; } export type DeviceType = 'xs' | 'sm' | 'md' | 'lg' | 'all'; @@ -133,6 +130,11 @@ export class ItemsControl { end: number; } +export class Vertical { + enabled: boolean; + height: number; +} + export class Touch { active?: boolean; swipe: string; @@ -152,7 +154,8 @@ export class NguCarousel { loop?: boolean; touch?: boolean; easing?: string; - RTL: boolean; + RTL?: boolean; + vertical?: Vertical; } export class Grid { @@ -171,26 +174,26 @@ export interface Point { export type Custom = 'banner'; export type Animate = 'lazy'; - - ``` -| Command | Type | Required | Description | -| --- | --- | --- | --- | -| `grid` | Object | Yes | **xs** - mobile, **sm** - tablet, **md** - desktop, **lg** - large desktops, **all** - fixed width (When you use **all** make others 0 and vise versa) | -| `slide` | number | optional | It is used to slide the number items on click | -| `speed` | milli seconds | optional | It is used for time taken to slide the number items | -| `interval` | milli seconds | optional | It is used to make carousel auto slide with given value. interval defines the interval between slides | -| `load` | number | optional | is used to load the items similar to pagination. the carousel will tigger the carouslLoad function to load another set of items. it will help you to improve the performance of the app.**`(carouselLoad)="myfunc($event)"`** | -| `point.visible` | boolean | optional | It is used to indicate no. of slides and also shows the current active slide. | -| `point.pointStyle` | string | optional | It is used to customize the point indicator. make sure your check the guide. | -| `point.hideOnSingleSlide` | boolean | optional | It is used to hide the point indicator when slide is less than one. | -| `touch` | boolean | optional | It is used to active touch support to the carousel. | -| `easing` | string | optional | It is used to define the easing style of the carousel. Only define the ease name without any timing like `ease`,`ease-in` | -| `loop` | boolean | optional | It is used to loop the `ngu-item | ngu-tile`. It must be true for `interval` | -| `animation` | string | optional | It is used to animate the sliding items. currently it only supports `lazy`. more coming soon and also with custom css animation option | -| `custom` | string | optional | It is you to define the purpose of the carousel. currently it only supports `banner`. more coming soon and also with custom css animation option | -| `RTL` | boolean | optional | This option enable the `rtl` direction and act as rtl. By default it is `ltr` | +| Command | Type | Required | Description | +| ------------------------- | ------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `grid` | Object | Yes | **xs** - mobile, **sm** - tablet, **md** - desktop, **lg** - large desktops, **all** - fixed width (When you use **all** make others 0 and vise versa) | +| `slide` | number | optional | It is used to slide the number items on click | +| `speed` | milli seconds | optional | It is used for time taken to slide the number items | +| `interval` | milli seconds | optional | It is used to make carousel auto slide with given value. interval defines the interval between slides | +| `load` | number | optional | is used to load the items similar to pagination. the carousel will tigger the carouslLoad function to load another set of items. it will help you to improve the performance of the app.**`(carouselLoad)="myfunc($event)"`** | +| `point.visible` | boolean | optional | It is used to indicate no. of slides and also shows the current active slide. | +| `point.pointStyle` | string | optional | It is used to customize the point indicator. make sure your check the guide. | +| `point.hideOnSingleSlide` | boolean | optional | It is used to hide the point indicator when slide is less than one. | +| `touch` | boolean | optional | It is used to active touch support to the carousel. | +| `easing` | string | optional | It is used to define the easing style of the carousel. Only define the ease name without any timing like `ease`,`ease-in` | +| `loop` | boolean | optional | It is used to loop the `ngu-item | ngu-tile`. It must be true for `interval` | +| `animation` | string | optional | It is used to animate the sliding items. currently it only supports `lazy`. more coming soon and also with custom css animation option | +| `custom` | string | optional | It is you to define the purpose of the carousel. currently it only supports `banner`. more coming soon and also with custom css animation option | +| `RTL` | boolean | optional | This option enable the `rtl` direction and act as rtl. By default it is `ltr` | +| `vertical.enabled` | boolean | optional | This option enable the `vertical` direction | +| `vertical.height` | boolean | optional | This option is used to set the height of the carousel | ### Custom css for Point @@ -203,14 +206,12 @@ export type Animate = 'lazy'; This is HTML I'm using in the carousel. Add your own css according to this elements in `pointStyles`. check below guide for more details. ```html - - ``` * `inputs` is an `Input` and It accepts `NguCarousel`. @@ -218,18 +219,17 @@ This is HTML I'm using in the carousel. Add your own css according to this eleme * `onMove` is an `Output` which triggered on every slide before start and it will emit `$event` as `NguCarouselStore` object. * `carouselLoad` is an `Output` which triggered when slide reaches the end on items based on inputs `load`. - ## Carousel Service ```javascript import { NguCarouselService } from '@ngu/carousel'; ``` + This carousel Service supports: * `reset(token)` - This function will reset the carousel * `moveToSlide(token, index, animate)` - This function is used to move to index with animation control. - # Getstarted guide ## Banner with Custom point style @@ -261,7 +261,8 @@ import { NguCarousel, NguCarouselStore } from '@ngu/carousel'; `, - styles: [` + styles: [ + ` .bannerStyle h1 { background-color: #ccc; min-height: 300px; @@ -291,15 +292,126 @@ import { NguCarousel, NguCarouselStore } from '@ngu/carousel'; border-radius: 999px; right: 0; } - `] + ` + ] }) export class Sample implements OnInit { + ngOnInit() { + this.carouselBanner = { + grid: { xs: 1, sm: 1, md: 1, lg: 1, all: 0 }, + slide: 1, + speed: 400, + interval: 4000, + point: { + visible: true, + pointStyles: ` + .ngucarouselPoint { + list-style-type: none; + text-align: center; + padding: 12px; + margin: 0; + white-space: nowrap; + overflow: auto; + position: absolute; + width: 100%; + bottom: 20px; + left: 0; + box-sizing: border-box; + } + .ngucarouselPoint li { + display: inline-block; + border-radius: 999px; + background: rgba(255, 255, 255, 0.55); + padding: 5px; + margin: 0 3px; + transition: .4s ease all; + } + .ngucarouselPoint li.active { + background: white; + width: 10px; + } + ` + }, + load: 2, + loop: true, + touch: true + }; + } + /* It will be triggered on every slide*/ + onmoveFn(data: NguCarouselStore) { + console.log(data); + } +} +``` - ngOnInit(){ +## Banner with Vertical carousel +```javascript +import { Component } from '@angular/core'; +import { NguCarousel, NguCarouselStore } from '@ngu/carousel'; + +@Component({ + selector: 'app-carousel', + template: ` + + + +

1

+
+ + +

2

+
+ + +

3

+
+ + + +
+ `, + styles: [ + ` + .bannerStyle h1 { + background-color: #ccc; + min-height: 300px; + text-align: center; + line-height: 300px; + } + .leftRs { + position: absolute; + margin: auto; + top: 0; + bottom: 0; + width: 50px; + height: 50px; + box-shadow: 1px 2px 10px -1px rgba(0, 0, 0, .3); + border-radius: 999px; + left: 0; + } + + .rightRs { + position: absolute; + margin: auto; + top: 0; + bottom: 0; + width: 50px; + height: 50px; + box-shadow: 1px 2px 10px -1px rgba(0, 0, 0, .3); + border-radius: 999px; + right: 0; + } + ` + ] +}) +export class Sample implements OnInit { + ngOnInit() { this.carouselBanner = { - grid: {xs: 1, sm: 1, md: 1, lg: 1, all: 0}, + grid: { xs: 1, sm: 1, md: 1, lg: 1, all: 0 }, slide: 1, speed: 400, interval: 4000, @@ -335,17 +447,19 @@ export class Sample implements OnInit { }, load: 2, loop: true, - touch: true - } + touch: true, // touch is not currently in active for vertical carousel, will enable it in future build + vertical { + enabled: true, + height: 400 + } + }; } /* It will be triggered on every slide*/ onmoveFn(data: NguCarouselStore) { console.log(data); } - } - ``` ## Tile with Service @@ -579,4 +693,4 @@ export class Sample implements OnInit { ## License -[MIT](LICENSE) license. \ No newline at end of file +[MIT](LICENSE) license. diff --git a/package.json b/package.json index ca1af67c..5493a5cf 100644 --- a/package.json +++ b/package.json @@ -1,32 +1,33 @@ { - "name": "ngu-carousel", - "version": "1.4.6", - "description": "Angular Universal carousel", - "scripts": { - "transpile": "ngc ", - "package": "rollup -c", - "minify": "uglifyjs dist/bundles/ngucarousel.umd.js --screw-ie8 --compress --mangle --comments --output dist/bundles/ngucarousel.umd.min.js", - "build": "npm run transpile && npm run package && npm run minify", - "postinstall": "npm run build" - }, - "devDependencies": { - "@angular/compiler": "^4.2.4", - "@angular/compiler-cli": "^4.2.4", - "@types/hammerjs": "^2.0.35", - "rollup": "^0.43.0", - "typescript": "^2.3.4", - "uglify-js": "^3.0.19" - }, - "dependencies": { - "@angular/common": "^4.2.4", - "@angular/core": "^4.2.4", - "@angular/platform-browser": "^4.2.4", - "hammerjs": "^2.0.8", - "rxjs": "^5.5.2" - }, - "peerDependencies": { - "@angular/common": ">=4.0.0", - "@angular/core": ">=4.0.0", - "@angular/platform-browser": ">=4.0.0" - } + "name": "ngu-carousel", + "version": "1.4.8", + "description": "Angular Universal carousel", + "scripts": { + "transpile": "ngc ", + "package": "rollup -c", + "minify": + "uglifyjs dist/bundles/ngucarousel.umd.js --screw-ie8 --compress --mangle --comments --output dist/bundles/ngucarousel.umd.min.js", + "build": "npm run transpile && npm run package && npm run minify", + "postinstall": "npm run build" + }, + "devDependencies": { + "@angular/compiler": "^4.2.4", + "@angular/compiler-cli": "^4.2.4", + "@types/hammerjs": "^2.0.35", + "rollup": "^0.43.0", + "typescript": "^2.3.4", + "uglify-js": "^3.0.19" + }, + "dependencies": { + "@angular/common": "^4.2.4", + "@angular/core": "^4.2.4", + "@angular/platform-browser": "^4.2.4", + "hammerjs": "^2.0.8", + "rxjs": "^5.5.2" + }, + "peerDependencies": { + "@angular/common": ">=4.0.0", + "@angular/core": ">=4.0.0", + "@angular/platform-browser": ">=4.0.0" + } } diff --git a/src/ngu-carousel/ngu-carousel.component.ts b/src/ngu-carousel/ngu-carousel.component.ts index 50a7f1cb..e3a4edf8 100644 --- a/src/ngu-carousel/ngu-carousel.component.ts +++ b/src/ngu-carousel/ngu-carousel.component.ts @@ -34,7 +34,7 @@ import { NguCarouselService } from './../ngu-carousel.service'; @Component({ // tslint:disable-next-line:component-selector selector: 'ngu-carousel', - template: `
`, + template: `
`, styles: [ ` :host { @@ -45,14 +45,18 @@ import { NguCarouselService } from './../ngu-carousel.service'; :host.ngurtl { direction: rtl; } + + .nguvertical { + flex-direction: column; + } .ngucarousel .ngucarousel-inner { position: relative; overflow: hidden; } .ngucarousel .ngucarousel-inner .ngucarousel-items { - white-space: nowrap; position: relative; + display: flex; } .banner .ngucarouselPointDefault .ngucarouselPoint { @@ -101,21 +105,24 @@ import { NguCarouselService } from './../ngu-carousel.service'; }) export class NguCarouselComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy, OnChanges { - withAnim: boolean; - carouselSerSub: Subscription; - directionSym: string; - itemsSubscribe: Subscription; - carouselCssNode: any; - pointIndex: number; + styleSelector: string; + private carouselSerSub: Subscription; + private directionSym: string; + private itemsSubscribe: Subscription; + private carouselCssNode: any; + private pointIndex: number; + private withAnim: boolean; pointers: number; // tslint:disable-next-line:no-input-rename - @Input('inputs') userData: any; - // @Input('moveToSlide') moveToSlide: number; + @Input('inputs') private userData: any; + // tslint:disable-next-line:no-input-rename + @Input('reset') private reseter: boolean; - @Output('carouselLoad') carouselLoad = new EventEmitter(); - @Output('onMove') onMove = new EventEmitter(); - @Output('initData') initData = new EventEmitter(); + @Output('carouselLoad') private carouselLoad = new EventEmitter(); + // tslint:disable-next-line:no-output-on-prefix + @Output('onMove') private onMove = new EventEmitter(); + @Output('initData') private initData = new EventEmitter(); @ContentChildren(NguCarouselItemDirective, { read: ElementRef }) private items: QueryList; @@ -153,7 +160,7 @@ export class NguCarouselComponent private onScrolling: any; private carouselInt: any; - public Arr1 = Array; + private Arr1 = Array; public pointNumbers: Array = []; public data: NguCarouselStore = { type: 'fixed', @@ -179,7 +186,10 @@ export class NguCarouselComponent isEnd: false, isFirst: true, isLast: false, - RTL: false + RTL: false, + button: { visibility: 'disabled' }, + point: true, + vertical: { enabled: false, height: 400 } }; public listener1: any; @@ -198,17 +208,12 @@ export class NguCarouselComponent @Inject(PLATFORM_ID) private platformId: Object ) {} - ngOnChanges(changes: SimpleChanges) { - // this.moveToSlide > -1 && - // !changes.moveToSlide.firstChange && - // this.moveTo(changes.moveToSlide.currentValue); - } + ngOnChanges(changes: SimpleChanges) {} ngOnInit() { this.carousel = this.el.nativeElement; this.carouselMain = this.carouselMain1.nativeElement; this.carouselInner = this.carouselInner1.nativeElement; - // this.carouselItems = this.carouselInner.getElementsByClassName('item'); this.rightBtn = this.next.nativeElement; this.leftBtn = this.prev.nativeElement; @@ -218,11 +223,21 @@ export class NguCarouselComponent this.userData.easing = this.userData.easing || 'cubic-bezier(0, 0, 0.2, 1)'; this.data.touch.active = this.userData.touch || false; this.data.RTL = this.userData.RTL ? true : false; + + if (this.userData.vertical && this.userData.vertical.enabled) { + this.data.vertical.enabled = this.userData.vertical.enabled; + this.data.vertical.height = this.userData.vertical.height; + } this.directionSym = this.data.RTL ? '' : '-'; + this.data.point = + this.userData.point && typeof this.userData.point.visible !== 'undefined' + ? this.userData.point.visible + : true; this.withAnim = true; this.carouselSize(); // const datas = this.itemsElements.first.nativeElement.getBoundingClientRect().width; + this.carouselSerSub = this.carouselSer.getData.subscribe(res => { if (res.id === this.data.token) { if (res.ref === 'moveToSlide') { @@ -256,7 +271,9 @@ export class NguCarouselComponent if (isPlatformBrowser(this.platformId)) { this.carouselInterval(); this.onWindowScrolling(); - this.touch(); + if (!this.data.vertical.enabled) { + this.touch(); + } this.listener3 = this.renderer.listen('window', 'resize', event => { this.onResizing(event); }); @@ -267,8 +284,6 @@ export class NguCarouselComponent this.carouselPoint(); this.buttonControl(); }); - // tslint:disable-next-line:no-unused-expression - // this.moveToSlide > -1 && this.moveTo(this.moveToSlide); } ngAfterViewInit() { @@ -292,40 +307,26 @@ export class NguCarouselComponent // tslint:disable-next-line:no-unused-expression this.itemsSubscribe && this.itemsSubscribe.unsubscribe(); this.carouselSerSub && this.carouselSerSub.unsubscribe(); + this.carouselLoad.complete(); // remove listeners - this.listener1(); - this.listener2(); - if (this.listener3) { - this.listener3(); - } - if (this.listener4) { - this.listener4(); - } - if (this.listener5) { - this.listener5(); - } - if (this.listener6) { - this.listener6(); - } - if (this.listener7) { - this.listener7(); - } - if (this.listener8) { - this.listener8(); + for (let i = 1; i <= 8; i++) { + // tslint:disable-next-line:no-eval + eval(`this.listener${i} && this.listener${i}()`); } } - private onResizing(event: any) { + private onResizing(event: any): void { clearTimeout(this.onResize); this.onResize = setTimeout(() => { - // tslint:disable-next-line:no-unused-expression - this.data.deviceWidth !== event.target.outerWidth && + if (this.data.deviceWidth !== event.target.outerWidth) { + this.setStyle(this.carouselInner, 'transition', ``); this.storeCarouselData(); + } }, 500); } - /* Get Touch input */ + /** Get Touch input */ private touch(): void { if (this.userData.touch) { const hammertime = new Hammer(this.carouselInner); @@ -334,26 +335,43 @@ export class NguCarouselComponent hammertime.on('panstart', (ev: any) => { this.data.carouselWidth = this.carouselInner.offsetWidth; this.data.touchTransform = this.data.transform[this.data.deviceType]; - this.data.dexVal = 0; this.setStyle(this.carouselInner, 'transition', ''); }); - hammertime.on('panleft', (ev: any) => { - this.touchHandling('panleft', ev); - }); - hammertime.on('panright', (ev: any) => { - this.touchHandling('panright', ev); - }); + if (this.data.vertical.enabled) { + hammertime.on('panup', (ev: any) => { + this.touchHandling('panleft', ev); + }); + hammertime.on('pandown', (ev: any) => { + this.touchHandling('panright', ev); + }); + } else { + hammertime.on('panleft', (ev: any) => { + this.touchHandling('panleft', ev); + }); + hammertime.on('panright', (ev: any) => { + this.touchHandling('panright', ev); + }); + } hammertime.on('panend', (ev: any) => { - // this.setStyle(this.carouselInner, 'transform', ''); - this.data.touch.velocity = ev.velocity; - let direc = 0; - if (!this.data.RTL) { - direc = this.data.touch.swipe === 'panright' ? 0 : 1; + if (Math.abs(ev.velocity) > 1) { + this.data.touch.velocity = ev.velocity; + let direc = 0; + if (!this.data.RTL) { + direc = this.data.touch.swipe === 'panright' ? 0 : 1; + } else { + direc = this.data.touch.swipe === 'panright' ? 1 : 0; + } + this.carouselScrollOne(direc); } else { - direc = this.data.touch.swipe === 'panright' ? 1 : 0; + this.data.dexVal = 0; + this.setStyle( + this.carouselInner, + 'transition', + 'transform 324ms cubic-bezier(0, 0, 0.2, 1)' + ); + this.setStyle(this.carouselInner, 'transform', ''); } - this.carouselScrollOne(direc); }); hammertime.on('hammer.input', function(ev) { // allow nested touch events to no propagate, this may have other side affects but works for now. @@ -363,7 +381,7 @@ export class NguCarouselComponent } } - /* handle touch input */ + /** handle touch input */ private touchHandling(e: string, ev: any): void { // 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 @@ -371,11 +389,15 @@ export class NguCarouselComponent return; } - ev = Math.abs(ev.deltaX); + ev = Math.abs(this.data.vertical.enabled ? ev.deltaY : ev.deltaX); let valt = ev - this.data.dexVal; valt = this.data.type === 'responsive' - ? Math.abs(ev - this.data.dexVal) / this.data.carouselWidth * 100 + ? Math.abs(ev - this.data.dexVal) / + (this.data.vertical.enabled + ? this.data.vertical.height + : this.data.carouselWidth) * + 100 : valt; this.data.dexVal = ev; this.data.touch.swipe = e; @@ -391,23 +413,37 @@ export class NguCarouselComponent : this.data.touchTransform - valt; } if (this.data.touchTransform > 0) { - this.setStyle( - this.carouselInner, - 'transform', - this.data.type === 'responsive' - ? `translate3d(${this.directionSym}${ - this.data.touchTransform - }%, 0px, 0px)` - : `translate3d(${this.directionSym}${ - this.data.touchTransform - }px, 0px, 0px)` - ); + if (this.data.type === 'responsive') { + this.setStyle( + this.carouselInner, + 'transform', + this.data.vertical.enabled + ? `translate3d(0, ${this.directionSym}${ + this.data.touchTransform + }%, 0)` + : `translate3d(${this.directionSym}${ + this.data.touchTransform + }%, 0, 0)` + ); + } else { + this.setStyle( + this.carouselInner, + 'transform', + this.data.vertical.enabled + ? `translate3d(0, ${this.directionSym}${ + this.data.touchTransform + }px, 0)` + : `translate3d(${this.directionSym}${ + this.data.touchTransform + }px, 0px, 0px)` + ); + } } else { this.data.touchTransform = 0; } } - /* this used to disable the scroll when it is not on the display */ + /** this used to disable the scroll when it is not on the display */ private onWindowScrolling(): void { const top = this.carousel.offsetTop; const scrollY = window.scrollY; @@ -424,7 +460,7 @@ export class NguCarouselComponent } } - /* store data based on width of the screen for the carousel */ + /** store data based on width of the screen for the carousel */ private storeCarouselData(): void { if (isPlatformBrowser(this.platformId)) { this.data.deviceWidth = window.innerWidth; @@ -467,14 +503,14 @@ export class NguCarouselComponent this.carouselPoint(); } - /* Used to reset the carousel */ - private reset(): void { + /** Used to reset the carousel */ + public reset(): void { this.carouselCssNode.innerHTML = ''; this.moveTo(0); this.carouselPoint(); } - /* Init carousel point */ + /** Init carousel point */ private carouselPoint(): void { // if (this.userData.point.visible === true) { const Nos = this.items.length - (this.data.items - this.data.slideItems); @@ -502,13 +538,13 @@ export class NguCarouselComponent // } } - /* change the active point in carousel */ + /** change the active point in carousel */ private carouselPointActiver(): void { const i = Math.ceil(this.data.currentSlide / this.data.slideItems); this.pointers = i; } - /* this function is used to scoll the carousel when point is clicked */ + /** this function is used to scoll the carousel when point is clicked */ public moveTo(index: number) { if (this.pointers !== index && index < this.pointIndex) { let slideremains = 0; @@ -528,51 +564,80 @@ export class NguCarouselComponent } } - /* set the style of the carousel based the inputs data */ + /** set the style of the carousel based the inputs data */ private carouselSize(): void { this.data.token = this.generateID(); let dism = ''; - const styleid = - '.' + - this.data.token + - ' > .ngucarousel > .ngucarousel-inner > .ngucarousel-items >'; + this.styleSelector = `.${ + this.data.token + } > .ngucarousel > .ngucarousel-inner > .ngucarousel-items`; if (this.userData.custom === 'banner') { this.renderer.addClass(this.carousel, 'banner'); } if (this.userData.animation === 'lazy') { - dism += `${styleid} .item {transition: transform .6s ease;}`; + dism += `${this.styleSelector} > .item {transition: transform .6s ease;}`; } let itemStyle = ''; - if (this.data.type === 'responsive') { + if (this.data.vertical.enabled) { + const itemWidth_xs = `${this.styleSelector} > .item {height: ${this.data + .vertical.height / +this.userData.grid.xs}px}`; + const itemWidth_sm = `${this.styleSelector} > .item {height: ${this.data + .vertical.height / +this.userData.grid.sm}px}`; + const itemWidth_md = `${this.styleSelector} > .item {height: ${this.data + .vertical.height / +this.userData.grid.md}px}`; + const itemWidth_lg = `${this.styleSelector} > .item {height: ${this.data + .vertical.height / +this.userData.grid.lg}px}`; + + itemStyle = `@media (max-width:767px){${itemWidth_xs}} + @media (min-width:768px){${itemWidth_sm}} + @media (min-width:992px){${itemWidth_md}} + @media (min-width:1200px){${itemWidth_lg}}`; + } else if (this.data.type === 'responsive') { const itemWidth_xs = this.userData.type === 'mobile' - ? `${styleid} .item {width: ${95 / +this.userData.grid.xs}%}` - : `${styleid} .item {width: ${100 / +this.userData.grid.xs}%}`; - - const itemWidth_sm = - styleid + ' .item {width: ' + 100 / +this.userData.grid.sm + '%}'; - const itemWidth_md = - styleid + ' .item {width: ' + 100 / +this.userData.grid.md + '%}'; - const itemWidth_lg = - styleid + ' .item {width: ' + 100 / +this.userData.grid.lg + '%}'; + ? `${this.styleSelector} .item {flex: 0 0 ${95 / + +this.userData.grid.xs}%}` + : `${this.styleSelector} .item {flex: 0 0 ${100 / + +this.userData.grid.xs}%}`; + + const itemWidth_sm = `${this.styleSelector} > .item {flex: 0 0 ${100 / + +this.userData.grid.sm}%}`; + const itemWidth_md = `${this.styleSelector} > .item {flex: 0 0 ${100 / + +this.userData.grid.md}%}`; + const itemWidth_lg = `${this.styleSelector} > .item {flex: 0 0 ${100 / + +this.userData.grid.lg}%}`; itemStyle = `@media (max-width:767px){${itemWidth_xs}} @media (min-width:768px){${itemWidth_sm}} @media (min-width:992px){${itemWidth_md}} @media (min-width:1200px){${itemWidth_lg}}`; } else { - itemStyle = `${styleid} .item {width: ${this.userData.grid.all}px}`; + itemStyle = `${this.styleSelector} .item {flex: 0 0 ${ + this.userData.grid.all + }px}`; } this.renderer.addClass(this.carousel, this.data.token); - this.data.RTL && this.renderer.addClass(this.carousel, 'ngurtl'); + if (this.data.vertical.enabled) { + this.renderer.addClass(this.carouselInner, 'nguvertical'); + this.renderer.setStyle( + this.forTouch.nativeElement, + 'height', + `${this.data.vertical.height}px` + ); + } + + // tslint:disable-next-line:no-unused-expression + this.data.RTL && + !this.data.vertical.enabled && + this.renderer.addClass(this.carousel, 'ngurtl'); this.createStyleElem(`${dism} ${itemStyle}`); } - /* logic to scroll the carousel step 1 */ + /** logic to scroll the carousel step 1 */ private carouselScrollOne(Btn: number): void { let itemSpeed = this.data.speed; let translateXval, @@ -641,14 +706,12 @@ export class NguCarouselComponent // cubic-bezier(0.15, 1.04, 0.54, 1.13) } - /* logic to scroll the carousel step 2 */ + /** logic to scroll the carousel step 2 */ private carouselScrollTwo( Btn: number, currentSlide: number, itemSpeed: number ): void { - // tslint:disable-next-line:no-unused-expression - if (this.data.dexVal !== 0) { const val = Math.abs(this.data.touch.velocity); let somt = Math.floor( @@ -661,7 +724,7 @@ export class NguCarouselComponent itemSpeed = somt < 200 ? 200 : somt; this.data.dexVal = 0; } - console.log(this.withAnim); + if (this.withAnim) { this.setStyle( this.carouselInner, @@ -687,60 +750,51 @@ export class NguCarouselComponent this.carouselLoadTrigger(); this.buttonControl(); this.withAnim = true; - console.log(this.withAnim); } - /* boolean function for making isFirst and isLast */ + /** boolean function for making isFirst and isLast */ private btnBoolean(first: number, last: number) { this.data.isFirst = first ? true : false; this.data.isLast = last ? true : false; } - /* set the transform style to scroll the carousel */ + private transformString(grid: string, slide: number): string { + let collect = ''; + collect += `${this.styleSelector} { transform: translate3d(`; + + if (this.data.vertical.enabled) { + this.data.transform[grid] = + this.data.vertical.height / this.userData.grid[grid] * slide; + collect += `0, -${this.data.transform[grid]}px, 0`; + } else { + this.data.transform[grid] = 100 / this.userData.grid[grid] * slide; + collect += `${this.directionSym}${this.data.transform[grid]}%, 0, 0`; + } + collect += `); }`; + return collect; + } + + /** set the transform style to scroll the carousel */ private transformStyle(slide: number): void { let slideCss = ''; if (this.data.type === 'responsive') { - this.data.transform.xs = 100 / this.userData.grid.xs * slide; - this.data.transform.sm = 100 / this.userData.grid.sm * slide; - this.data.transform.md = 100 / this.userData.grid.md * slide; - this.data.transform.lg = 100 / this.userData.grid.lg * slide; - slideCss = `@media (max-width: 767px) { - .${ - this.data.token - } > .ngucarousel > .ngucarousel-inner > .ngucarousel-items { transform: translate3d(${ - this.directionSym - }${this.data.transform.xs}%, 0, 0); } } - @media (min-width: 768px) { - .${ - this.data.token - } > .ngucarousel > .ngucarousel-inner > .ngucarousel-items { transform: translate3d(${ - this.directionSym - }${this.data.transform.sm}%, 0, 0); } } - @media (min-width: 992px) { - .${ - this.data.token - } > .ngucarousel > .ngucarousel-inner > .ngucarousel-items { transform: translate3d(${ - this.directionSym - }${this.data.transform.md}%, 0, 0); } } - @media (min-width: 1200px) { - .${ - this.data.token - } > .ngucarousel > .ngucarousel-inner > .ngucarousel-items { transform: translate3d(${ - this.directionSym - }${this.data.transform.lg}%, 0, 0); } }`; + slideCss = `@media (max-width: 767px) {${this.transformString( + 'xs', + slide + )}} + @media (min-width: 768px) {${this.transformString('sm', slide)} } + @media (min-width: 992px) {${this.transformString('md', slide)} } + @media (min-width: 1200px) {${this.transformString('lg', slide)} }`; } else { this.data.transform.all = this.userData.grid.all * slide; - slideCss = `.${ - this.data.token - } > .ngucarousel > .ngucarousel-inner > .ngucarousel-items { transform: translate3d(${ + slideCss = `${this.styleSelector} { transform: translate3d(${ this.directionSym }${this.data.transform.all}px, 0, 0);`; } - // this.renderer.createText(this.carouselCssNode, slideCss); this.carouselCssNode.innerHTML = slideCss; } - /* this will trigger the carousel to load the items */ + /** this will trigger the carousel to load the items */ private carouselLoadTrigger(): void { if (typeof this.userData.load === 'number') { // tslint:disable-next-line:no-unused-expression @@ -750,7 +804,7 @@ export class NguCarouselComponent } } - /* generate Class for each carousel to set specific style */ + /** generate Class for each carousel to set specific style */ private generateID(): string { let text = ''; const possible = @@ -762,7 +816,7 @@ export class NguCarouselComponent return `ngucarousel${text}`; } - /* handle the auto slide */ + /** handle the auto slide */ private carouselInterval(): void { if (typeof this.userData.interval === 'number' && this.data.loop) { this.listener4 = this.renderer.listen( @@ -811,7 +865,7 @@ export class NguCarouselComponent } } - /* pause interval for specific time */ + /** pause interval for specific time */ private carouselIntervalEvent(ev: number): void { this.evtValue = ev; if (this.evtValue === 0) { @@ -825,7 +879,7 @@ export class NguCarouselComponent } } - /* animate the carousel items */ + /** animate the carousel items */ private carouselAnimator( direction: number, start: number, @@ -840,7 +894,6 @@ export class NguCarouselComponent if (direction === 1) { for (let i = start - 1; i < end; i++) { val = val * 2; - // tslint:disable-next-line:no-unused-expression itemList[i] && this.setStyle( itemList[i].nativeElement, @@ -851,7 +904,6 @@ export class NguCarouselComponent } else { for (let i = end - 1; i >= start - 1; i--) { val = val * 2; - // tslint:disable-next-line:no-unused-expression itemList[i] && this.setStyle( itemList[i].nativeElement, @@ -867,23 +919,19 @@ export class NguCarouselComponent }, speed * 0.7); } - /* control button for loop */ + /** control button for loop */ private buttonControl(): void { + let arr = []; if (!this.data.loop || (this.data.isFirst && this.data.isLast)) { - this.setStyle( - this.leftBtn, - 'display', - this.data.isFirst ? 'none' : 'block' - ); - this.setStyle( - this.rightBtn, - 'display', + arr = [ + this.data.isFirst ? 'none' : 'block', this.data.isLast ? 'none' : 'block' - ); + ]; } else { - this.setStyle(this.leftBtn, 'display', 'block'); - this.setStyle(this.rightBtn, 'display', 'block'); + arr = ['block', 'block']; } + this.setStyle(this.leftBtn, 'display', arr[0]); + this.setStyle(this.rightBtn, 'display', arr[1]); } /** Short form for setElementStyle */ diff --git a/src/ngu-carousel/ngu-carousel.interface.ts b/src/ngu-carousel/ngu-carousel.interface.ts index 15581590..6099bacf 100644 --- a/src/ngu-carousel/ngu-carousel.interface.ts +++ b/src/ngu-carousel/ngu-carousel.interface.ts @@ -23,14 +23,29 @@ export class NguCarouselStore { isFirst: boolean; isLast: boolean; RTL: boolean; + button: NguButton; + point: boolean; + vertical: Vertical; } export type DeviceType = 'xs' | 'sm' | 'md' | 'lg' | 'all'; +export type ButtonVisible = 'disabled' | 'hide'; + export class ItemsControl { start: number; end: number; } +export class Vertical { + enabled: boolean; + height: number; +} + +export class NguButton { + visibility?: ButtonVisible; + elastic?: number; +} + export class Touch { active?: boolean; swipe: string; @@ -38,6 +53,7 @@ export class Touch { } export class Transfrom { + [key: string]: number; xs: number; sm: number; md: number; @@ -59,12 +75,13 @@ export class NguCarousel { touch?: boolean; easing?: string; RTL?: boolean; + button?: NguButton; + vertical?: Vertical; } export type Custom = 'banner'; export type Animate = 'lazy'; - export interface Point { visible: boolean; pointStyles?: string;