UNPKG

ngx-owl-carousel-o

Version:
1 lines 240 kB
{"version":3,"file":"ngx-owl-carousel-o.mjs","sources":["../../libs/ngx-owl-carousel-o/src/lib/carousel/owl-carousel-o-config.ts","../../libs/ngx-owl-carousel-o/src/lib/services/logger.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/carousel.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/navigation.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/window-ref.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/document-ref.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/autoplay.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/lazyload.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/animate.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/autoheight.service.ts","../../libs/ngx-owl-carousel-o/src/lib/services/hash.service.ts","../../libs/ngx-owl-carousel-o/src/lib/carousel/carousel-slide.directive.ts","../../libs/ngx-owl-carousel-o/src/lib/services/resize.service.ts","../../libs/ngx-owl-carousel-o/src/lib/carousel/stage/stage.component.ts","../../libs/ngx-owl-carousel-o/src/lib/carousel/carousel.component.ts","../../libs/ngx-owl-carousel-o/src/lib/carousel/owl-router-link.directive.ts","../../libs/ngx-owl-carousel-o/src/lib/models/SlidesOutputData.ts","../../libs/ngx-owl-carousel-o/src/lib/carousel/carousel.module.ts","../../libs/ngx-owl-carousel-o/src/lib/models/slide.model.ts","../../libs/ngx-owl-carousel-o/src/ngx-owl-carousel-o.ts"],"sourcesContent":["import { OwlOptions } from \"../models/owl-options.model\";\n\n/**\n * Defaults value of options\n */\nexport class OwlCarouselOConfig implements OwlOptions {\n items = 3;\n skip_validateItems = false;\n loop = false;\n center = false;\n rewind = false;\n\n mouseDrag = true;\n touchDrag = true;\n pullDrag = true;\n freeDrag = false;\n\n margin = 0;\n stagePadding = 0;\n\n merge = false;\n mergeFit = true;\n autoWidth = false;\n\n startPosition = 0;\n rtl = false;\n\n smartSpeed = 250;\n fluidSpeed = false;\n dragEndSpeed = false;\n\n responsive = {};\n responsiveRefreshRate = 200;\n\n // defaults to Navigation\n nav = false;\n navText = [ 'prev', 'next' ];\n navSpeed = false;\n slideBy = 1; // stage moves on 1 width of slide; if slideBy = 2, stage moves on 2 widths of slide\n dots = true;\n dotsEach = false;\n dotsData = false;\n dotsSpeed = false;\n\n // defaults to Autoplay\n autoplay = false;\n autoplayTimeout = 5000;\n autoplayHoverPause = false;\n autoplaySpeed = false;\n autoplayMouseleaveTimeout = 1;\n\n // defaults to LazyLoading\n lazyLoad = false;\n lazyLoadEager = 0;\n\n // defaults to Animate\n slideTransition = '';\n animateOut = false;\n animateIn = false;\n\n // defaults to AutoHeight\n autoHeight = false;\n\n // defaults to Hash\n URLhashListener = false;\n constructor() { }\n}\n\n/**\n * we can't read types from OwlOptions in javascript because of props have undefined value and types of those props are used for validating inputs\n * class below is copy of OwlOptions but its all props have string value showing certain type;\n * this is class is being used just in method _validateOptions() of CarouselService;\n */\nexport class OwlOptionsMockedTypes {\n items = 'number';\n skip_validateItems = 'boolean';\n loop = 'boolean';\n center = 'boolean';\n rewind = 'boolean';\n\n mouseDrag = 'boolean';\n touchDrag = 'boolean';\n pullDrag = 'boolean';\n freeDrag = 'boolean';\n\n margin = 'number';\n stagePadding = 'number';\n\n merge = 'boolean';\n mergeFit = 'boolean';\n autoWidth = 'boolean';\n\n startPosition = 'number|string';\n rtl = 'boolean';\n\n smartSpeed = 'number';\n fluidSpeed = 'boolean';\n dragEndSpeed = 'number|boolean';\n\n responsive = {};\n responsiveRefreshRate = 'number';\n\n // defaults to Navigation\n nav = 'boolean';\n navText = 'string[]';\n navSpeed = 'number|boolean';\n slideBy = 'number|string'; // stage moves on 1 width of slide; if slideBy = 2, stage moves on 2 widths of slide\n dots = 'boolean';\n dotsEach = 'number|boolean';\n dotsData = 'boolean';\n dotsSpeed = 'number|boolean';\n\n // defaults to Autoplay\n autoplay = 'boolean';\n autoplayTimeout = 'number';\n autoplayHoverPause = 'boolean';\n autoplaySpeed = 'number|boolean';\n autoplayMouseleaveTimeout = 'number';\n\n // defaults to LazyLoading\n lazyLoad = 'boolean';\n lazyLoadEager = 'number';\n\n // defaults to Animate\n slideTransition = 'string';\n animateOut = 'string|boolean';\n animateIn = 'string|boolean';\n\n // defaults to AutoHeight\n autoHeight = 'boolean';\n\n // defaults to Hash\n URLhashListener = \"boolean\";\n constructor() { }\n}","import { ErrorHandler, Injectable, isDevMode } from '@angular/core';\n\n@Injectable()\nexport class OwlLogger {\n\n constructor(private errorHandler: ErrorHandler) {}\n\n log(value: any, ...rest: any[]) {\n if (isDevMode()) {\n console.log(value, ...rest);\n }\n }\n\n error(error: Error) {\n this.errorHandler.handleError(error);\n }\n\n warn(value: any, ...rest: any[]) {\n console.warn(value, ...rest);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Subject, Observable } from 'rxjs';\n\nimport { StageData } from '../models/stage-data.model';\nimport { OwlDOMData } from '../models/owlDOM-data.model';\nimport { SlideModel } from '../models/slide.model';\n\n\nimport { CarouselSlideDirective } from '../carousel/carousel-slide.directive';\nimport { OwlCarouselOConfig, OwlOptionsMockedTypes } from '../carousel/owl-carousel-o-config';\nimport { OwlOptions } from '../models/owl-options.model';\n\nimport { NavData, DotsData } from '../models/navigation-data.models';\nimport { OwlLogger } from './logger.service';\n\n/**\n * Current state information and their tags.\n */\nexport class States {\n\tcurrent: {};\n\ttags: {\n\t\t[key: string]: string[];\n\t};\n}\n\n/**\n * Enumeration for types.\n * @enum {String}\n */\nexport enum Type {\n\tEvent = 'event',\n\tState = 'state'\n};\n\n/**\n * Enumeration for width.\n * @enum {String}\n */\nexport enum Width {\n\tDefault = 'default',\n\tInner = 'inner',\n\tOuter = 'outer'\n};\n\n/**\n * Model for coords of .owl-stage\n */\nexport class Coords {\n\tx: number;\n\ty: number;\n}\n\n/**\n * Model for all current data of carousel\n */\nexport class CarouselCurrentData {\n\towlDOMData: OwlDOMData;\n\tstageData: StageData;\n\tslidesData: SlideModel[];\n\tnavData: NavData;\n\tdotsData: DotsData;\n}\n\n@Injectable()\nexport class CarouselService {\n\t/**\n\t * Subject for passing data needed for managing View\n\t */\n\tprivate _viewSettingsShipper$ = new Subject<CarouselCurrentData>();\n\t/**\n\t * Subject for notification when the carousel got initializes\n\t */\n\tprivate _initializedCarousel$ = new Subject<string>();\n\n\t/**\n\t * Subject for notification when the carousel's settings start changinf\n\t */\n\tprivate _changeSettingsCarousel$ = new Subject<any>();\n\n\t/**\n\t * Subject for notification when the carousel's settings have changed\n\t */\n\tprivate _changedSettingsCarousel$ = new Subject<any>();\n\t/**\n\t * Subject for notification when the carousel starts translating or moving\n\t */\n\tprivate _translateCarousel$ = new Subject<string>();\n\t/**\n\t * Subject for notification when the carousel stopped translating or moving\n\t */\n\tprivate _translatedCarousel$ = new Subject<string>();\n\t/**\n\t * Subject for notification when the carousel's rebuilding caused by 'resize' event starts\n\t */\n\tprivate _resizeCarousel$ = new Subject<string>();\n\t/**\n\t * Subject for notification when the carousel's rebuilding caused by 'resize' event is ended\n\t */\n\tprivate _resizedCarousel$ = new Subject<string>();\n\t/**\n\t * Subject for notification when the refresh of carousel starts\n\t */\n\tprivate _refreshCarousel$ = new Subject<string>();\n\t/**\n\t * Subject for notification when the refresh of carousel is ended\n\t */\n\tprivate _refreshedCarousel$ = new Subject<string>();\n\t/**\n\t * Subject for notification when the dragging of carousel starts\n\t */\n\tprivate _dragCarousel$ = new Subject<string>();\n\t/**\n\t * Subject for notification when the dragging of carousel is ended\n\t */\n\tprivate _draggedCarousel$ = new Subject<string>();\n\n\t/**\n\t * Current settings for the carousel.\n\t */\n\tsettings: OwlOptions = {\n\t\titems: 0\n\t};\n\n\t/**\n\t * Initial data for setting classes to element .owl-carousel\n\t */\n\towlDOMData: OwlDOMData = {\n\t\trtl: false,\n\t\tisResponsive: false,\n\t\tisRefreshed: false,\n\t\tisLoaded: false,\n\t\tisLoading: false,\n\t\tisMouseDragable: false,\n\t\tisGrab: false,\n\t\tisTouchDragable: false\n\t};\n\n\t/**\n\t * Initial data of .owl-stage\n\t */\n\tstageData: StageData = {\n\t\ttransform: 'translate3d(0px,0px,0px)',\n\t\ttransition: '0s',\n\t\twidth: 0,\n\t\tpaddingL: 0,\n\t\tpaddingR: 0\n\t};\n\n\t/**\n\t * Data of every slide\n\t */\n\tslidesData: SlideModel[];\n\n\t/**\n\t * Data of navigation block\n\t */\n\tnavData: NavData;\n\n\t/**\n\t * Data of dots block\n\t */\n\tdotsData: DotsData;\n\n\t/**\n\t * Carousel width\n\t */\n\tprivate _width: number;\n\n\t/**\n\t * All real items.\n\t */\n\tprivate _items: CarouselSlideDirective[] = []; // is equal to this.slides\n\n\t/**\n\t * Array with width of every slide.\n\t */\n\tprivate _widths: any[] = [];\n\n\t/**\n\t * Currently suppressed events to prevent them from beeing retriggered.\n\t */\n\tprivate _supress: any = {};\n\n\t/**\n\t * References to the running plugins of this carousel.\n\t */\n\tprivate _plugins: any = {};\n\n\t/**\n\t * Absolute current position.\n\t */\n\tprivate _current: number | null = null;\n\n\t/**\n\t * All cloned items.\n\t */\n\tprivate _clones: any[] = [];\n\n\t/**\n\t * Merge values of all items.\n\t * @todo Maybe this could be part of a plugin.\n\t */\n\tprivate _mergers: any[] = [];\n\n\t/**\n\t * Animation speed in milliseconds.\n\t */\n\tprivate _speed: number | null = null;\n\n\t/**\n\t * Coordinates of all items in pixel.\n\t * @todo The name of this member is missleading.\n\t */\n\tprivate _coordinates: number[] = [];\n\n\t/**\n\t * Current breakpoint.\n\t * @todo Real media queries would be nice.\n\t */\n\tprivate _breakpoint: any = null;\n\n\t/**\n\t * Prefix for id of cloned slides\n\t */\n\tclonedIdPrefix = 'cloned-';\n\n\t/**\n\t * Current options set by the caller including defaults.\n\t */\n\t_options: OwlOptions = {};\n\n\t/**\n\t * Invalidated parts within the update process.\n\t */\n\tprivate _invalidated: any = {};\n\n\t// Is needed for tests\n\tget invalidated() {\n\t\treturn this._invalidated;\n\t}\n\t/**\n\t * Current state information and their tags.\n\t */\n\tprivate _states: States = {\n\t\tcurrent: {},\n\t\ttags: {\n\t\t\tinitializing: ['busy'],\n\t\t\tanimating: ['busy'],\n\t\t\tdragging: ['interacting']\n\t\t}\n\t};\n\n\t// is needed for tests\n\tget states() {\n\t\treturn this._states;\n\t}\n\n\t/**\n\t\t * Ordered list of workers for the update process.\n\t */\n\tprivate _pipe: any[] = [\n\t\t// {\n\t\t// filter: ['width', 'settings'],\n\t\t// run: () => {\n\t\t// this._width = this.carouselWindowWidth;\n\t\t// }\n\t\t// },\n\t\t{\n\t\t\tfilter: ['width', 'items', 'settings'],\n\t\t\trun: cache => {\n\t\t\t\tcache.current = this._items && this._items[this.relative(this._current)]?.id;\n\t\t\t}\n\t\t},\n\t\t// {\n\t\t// filter: ['items', 'settings'],\n\t\t// run: function() {\n\t\t// // this.$stage.children('.cloned').remove();\n\t\t// }\n\t\t// },\n\t\t{\n\t\t\tfilter: ['width', 'items', 'settings'],\n\t\t\trun: (cache) => {\n\t\t\t\tconst margin = this.settings.margin || '',\n\t\t\t\t\tgrid = !this.settings.autoWidth,\n\t\t\t\t\trtl = this.settings.rtl,\n\t\t\t\t\tcss = {\n\t\t\t\t\t\t'margin-left': rtl ? margin : '',\n\t\t\t\t\t\t'margin-right': rtl ? '' : margin\n\t\t\t\t\t};\n\n\t\t\t\tif (!grid) {\n\t\t\t\t\tthis.slidesData.forEach(slide => {\n\t\t\t\t\t\tslide.marginL = css['margin-left'];\n\t\t\t\t\t\tslide.marginR = css['margin-right'];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tcache.css = css;\n\t\t\t}\n\t\t}, {\n\t\t\tfilter: ['width', 'items', 'settings'],\n\t\t\trun: (cache) => {\n\t\t\t\tconst width: any = +(this.width() / this.settings.items).toFixed(3) - this.settings.margin,\n\t\t\t\t\tgrid = !this.settings.autoWidth,\n\t\t\t\t\twidths = [];\n\t\t\t\tlet merge = null,\n\t\t\t\t\titerator = this._items.length;\n\n\t\t\t\tcache.items = {\n\t\t\t\t\tmerge: false,\n\t\t\t\t\twidth: width\n\t\t\t\t};\n\n\t\t\t\twhile (iterator-- > 0) {\n\t\t\t\t\tmerge = this._mergers[iterator];\n\t\t\t\t\tmerge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;\n\t\t\t\t\tcache.items.merge = merge > 1 || cache.items.merge;\n\n\t\t\t\t\twidths[iterator] = !grid ? this._items[iterator].width ? this._items[iterator].width : width : width * merge;\n\t\t\t\t}\n\n\t\t\t\tthis._widths = widths;\n\n\t\t\t\tthis.slidesData.forEach((slide, i) => {\n\t\t\t\t\tslide.width = this._widths[i];\n\t\t\t\t\tslide.marginR = cache.css['margin-right'];\n\t\t\t\t\tslide.marginL = cache.css['margin-left'];\n\t\t\t\t});\n\t\t\t}\n\t\t}, {\n\t\t\tfilter: ['items', 'settings'],\n\t\t\trun: () => {\n\t\t\t\tconst clones: any[] = [],\n\t\t\t\t\titems: CarouselSlideDirective[] = this._items,\n\t\t\t\t\tsettings: any = this.settings,\n\t\t\t\t\t// TODO: Should be computed from number of min width items in stage\n\t\t\t\t\tview = Math.max(settings.items * 2, 4),\n\t\t\t\t\tsize = Math.ceil(items.length / 2) * 2;\n\t\t\t\tlet append: any[] = [],\n\t\t\t\t\tprepend: any[] = [],\n\t\t\t\t\trepeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0;\n\n\t\t\t\trepeat /= 2;\n\n\t\t\t\twhile (repeat-- > 0) {\n\t\t\t\t\t// Switch to only using appended clones\n\t\t\t\t\tclones.push(this.normalize(clones.length / 2, true));\n\t\t\t\t\tappend.push({ ...this.slidesData[clones[clones.length - 1]] });\n\t\t\t\t\tclones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));\n\t\t\t\t\tprepend.unshift({ ...this.slidesData[clones[clones.length - 1]] });\n\t\t\t\t}\n\n\t\t\t\tthis._clones = clones;\n\n\t\t\t\tappend = append.map(slide => {\n\t\t\t\t\tslide.id = `${this.clonedIdPrefix}${slide.id}`;\n\t\t\t\t\tslide.isActive = false;\n\t\t\t\t\tslide.isCloned = true;\n\t\t\t\t\treturn slide;\n\t\t\t\t});\n\n\t\t\t\tprepend = prepend.map(slide => {\n\t\t\t\t\tslide.id = `${this.clonedIdPrefix}${slide.id}`;\n\t\t\t\t\tslide.isActive = false;\n\t\t\t\t\tslide.isCloned = true;\n\t\t\t\t\treturn slide;\n\t\t\t\t});\n\n\t\t\t\tthis.slidesData = prepend.concat(this.slidesData).concat(append);\n\t\t\t}\n\t\t}, {\n\t\t\tfilter: ['width', 'items', 'settings'],\n\t\t\trun: () => {\n\t\t\t\tconst rtl = this.settings.rtl ? 1 : -1,\n\t\t\t\t\tsize = this._clones.length + this._items.length,\n\t\t\t\t\tcoordinates = [];\n\t\t\t\tlet iterator = -1,\n\t\t\t\t\tprevious = 0,\n\t\t\t\t\tcurrent = 0;\n\n\t\t\t\twhile (++iterator < size) {\n\t\t\t\t\tprevious = coordinates[iterator - 1] || 0;\n\t\t\t\t\tcurrent = this._widths[this.relative(iterator)] + this.settings.margin;\n\t\t\t\t\tcoordinates.push(previous + current * rtl);\n\t\t\t\t}\n\n\t\t\t\tthis._coordinates = coordinates;\n\t\t\t}\n\t\t}, {\n\t\t\tfilter: ['width', 'items', 'settings'],\n\t\t\trun: () => {\n\t\t\t\tconst padding = this.settings.stagePadding,\n\t\t\t\t\tcoordinates = this._coordinates,\n\t\t\t\t\tcss = {\n\t\t\t\t\t\t'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,\n\t\t\t\t\t\t'padding-left': padding || '',\n\t\t\t\t\t\t'padding-right': padding || ''\n\t\t\t\t\t};\n\n\t\t\t\tthis.stageData.width = css.width; // use this property in *ngIf directive for .owl-stage element\n\t\t\t\tthis.stageData.paddingL = css['padding-left'];\n\t\t\t\tthis.stageData.paddingR = css['padding-right'];\n\t\t\t}\n\t\t}, {\n\t\t\t// filter: [ 'width', 'items', 'settings' ],\n\t\t\t// run: cache => {\n\t\t\t// \t\t// this method sets the width for every slide, but I set it in different way earlier\n\t\t\t// \t\tconst grid = !this.settings.autoWidth,\n\t\t\t// \t\titems = this.$stage.children(); // use this.slidesData\n\t\t\t// let iterator = this._coordinates.length;\n\n\t\t\t// if (grid && cache.items.merge) {\n\t\t\t// while (iterator--) {\n\t\t\t// cache.css.width = this._widths[this.relative(iterator)];\n\t\t\t// items.eq(iterator).css(cache.css);\n\t\t\t// }\n\t\t\t// } else if (grid) {\n\t\t\t// cache.css.width = cache.items.width;\n\t\t\t// items.css(cache.css);\n\t\t\t// }\n\t\t\t// }\n\t\t\t// }, {\n\t\t\t// filter: [ 'items' ],\n\t\t\t// run: function() {\n\t\t\t// this._coordinates.length < 1 && this.$stage.removeAttr('style');\n\t\t\t// }\n\t\t\t// }, {\n\t\t\tfilter: ['width', 'items', 'settings'],\n\t\t\trun: cache => {\n\t\t\t\tlet current = cache.current ? this.slidesData.findIndex(slide => slide.id === cache.current) : 0;\n\t\t\t\tcurrent = Math.max(this.minimum(), Math.min(this.maximum(), current));\n\t\t\t\tthis.reset(current);\n\t\t\t}\n\t\t}, {\n\t\t\tfilter: ['position'],\n\t\t\trun: () => {\n\t\t\t\tthis.animate(this.coordinates(this._current));\n\t\t\t}\n\t\t}, {\n\t\t\tfilter: ['width', 'position', 'items', 'settings'],\n\t\t\trun: () => {\n\t\t\t\tconst rtl = this.settings.rtl ? 1 : -1,\n\t\t\t\t\tpadding = this.settings.stagePadding * 2,\n\t\t\t\t\tmatches = [];\n\t\t\t\tlet begin, end, inner, outer, i, n;\n\n\t\t\t\tbegin = this.coordinates(this.current());\n\t\t\t\tif (typeof begin === 'number') {\n\t\t\t\t\tbegin += padding;\n\t\t\t\t} else {\n\t\t\t\t\tbegin = 0;\n\t\t\t\t}\n\n\t\t\t\tend = begin + this.width() * rtl;\n\n\t\t\t\tif (rtl === -1 && this.settings.center) {\n\t\t\t\t\tconst result = this._coordinates.filter(element => {\n\t\t\t\t\t\treturn this.settings.items % 2 === 1 ? element >= begin : element > begin;\n\t\t\t\t\t});\n\t\t\t\t\tbegin = result.length ? result[result.length - 1] : begin;\n\t\t\t\t}\n\n\t\t\t\tfor (i = 0, n = this._coordinates.length; i < n; i++) {\n\t\t\t\t\tinner = Math.ceil(this._coordinates[i - 1] || 0);\n\t\t\t\t\touter = Math.ceil(Math.abs(this._coordinates[i]) + padding * rtl);\n\n\t\t\t\t\tif ((this._op(inner, '<=', begin) && (this._op(inner, '>', end)))\n\t\t\t\t\t\t|| (this._op(outer, '<', begin) && this._op(outer, '>', end))) {\n\t\t\t\t\t\tmatches.push(i);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.slidesData.forEach(slide => {\n\t\t\t\t\tslide.isActive = false;\n\t\t\t\t\treturn slide;\n\t\t\t\t});\n\t\t\t\tmatches.forEach(item => {\n\t\t\t\t\tthis.slidesData[item].isActive = true;\n\t\t\t\t});\n\n\t\t\t\tif (this.settings.center) {\n\t\t\t\t\tthis.slidesData.forEach(slide => {\n\t\t\t\t\t\tslide.isCentered = false;\n\t\t\t\t\t\treturn slide;\n\t\t\t\t\t});\n\t\t\t\t\tthis.slidesData[this.current()].isCentered = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t];\n\n\tconstructor(private logger: OwlLogger) { }\n\n\t/**\n\t * Makes _viewSettingsShipper$ Subject become Observable\n\t * @returns Observable of _viewSettingsShipper$ Subject\n\t */\n\tgetViewCurSettings(): Observable<CarouselCurrentData> {\n\t\treturn this._viewSettingsShipper$.asObservable();\n\t}\n\n\t/**\n\t * Makes _initializedCarousel$ Subject become Observable\n\t * @returns Observable of _initializedCarousel$ Subject\n\t */\n\tgetInitializedState(): Observable<string> {\n\t\treturn this._initializedCarousel$.asObservable()\n\t}\n\n\t/**\n\t * Makes _changeSettingsCarousel$ Subject become Observable\n\t * @returns Observable of _changeSettingsCarousel$ Subject\n\t */\n\tgetChangeState(): Observable<any> {\n\t\treturn this._changeSettingsCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _changedSettingsCarousel$ Subject become Observable\n\t * @returns Observable of _changedSettingsCarousel$ Subject\n\t */\n\tgetChangedState(): Observable<any> {\n\t\treturn this._changedSettingsCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _translateCarousel$ Subject become Observable\n\t * @returns Observable of _translateCarousel$ Subject\n\t */\n\tgetTranslateState(): Observable<string> {\n\t\treturn this._translateCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _translatedCarousel$ Subject become Observable\n\t * @returns Observable of _translatedCarousel$ Subject\n\t */\n\tgetTranslatedState(): Observable<string> {\n\t\treturn this._translatedCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _resizeCarousel$ Subject become Observable\n\t * @returns Observable of _resizeCarousel$ Subject\n\t */\n\tgetResizeState(): Observable<string> {\n\t\treturn this._resizeCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _resizedCarousel$ Subject become Observable\n\t * @returns Observable of _resizedCarousel$ Subject\n\t */\n\tgetResizedState(): Observable<string> {\n\t\treturn this._resizedCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _refreshCarousel$ Subject become Observable\n\t * @returns Observable of _refreshCarousel$ Subject\n\t */\n\tgetRefreshState(): Observable<string> {\n\t\treturn this._refreshCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _refreshedCarousel$ Subject become Observable\n\t * @returns Observable of _refreshedCarousel$ Subject\n\t */\n\tgetRefreshedState(): Observable<string> {\n\t\treturn this._refreshedCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _dragCarousel$ Subject become Observable\n\t * @returns Observable of _dragCarousel$ Subject\n\t */\n\tgetDragState(): Observable<string> {\n\t\treturn this._dragCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Makes _draggedCarousel$ Subject become Observable\n\t * @returns Observable of _draggedCarousel$ Subject\n\t */\n\tgetDraggedState(): Observable<string> {\n\t\treturn this._draggedCarousel$.asObservable();\n\t}\n\n\t/**\n\t * Setups custom options expanding default options\n\t * @param options custom options\n\t */\n\tsetOptions(options: OwlOptions) {\n\t\tconst configOptions: OwlOptions = new OwlCarouselOConfig();\n\t\tconst checkedOptions: OwlOptions = this._validateOptions(options, configOptions);\n\t\tthis._options = { ...configOptions, ...checkedOptions };\n\t}\n\n\t/**\n\t * Checks whether user's option are set properly. Cheking is based on typings;\n\t * @param options options set by user\n\t * @param configOptions default options\n\t * @returns checked and modified (if it's needed) user's options\n\t *\n\t * Notes:\n\t * \t- if user set option with wrong type, it'll be written in console\n\t */\n\tprivate _validateOptions(options: OwlOptions, configOptions: OwlOptions): OwlOptions {\n\t\tconst checkedOptions: OwlOptions = { ...options };\n\t\tconst mockedTypes = new OwlOptionsMockedTypes();\n\n\t\tconst setRightOption = (type: string, key: any): OwlOptions => {\n\t\t\tthis.logger.log(`options.${key} must be type of ${type}; ${key}=${options[key]} skipped to defaults: ${key}=${configOptions[key]}`);\n\t\t\treturn configOptions[key];\n\t\t};\n\n\t\tfor (const key in checkedOptions) {\n\t\t\tif (checkedOptions.hasOwnProperty(key)) {\n\n\t\t\t\t// condition could be shortened but it gets harder for understanding\n\t\t\t\tif (mockedTypes[key] === 'number') {\n\t\t\t\t\tif (this._isNumeric(checkedOptions[key])) {\n\t\t\t\t\t\tcheckedOptions[key] = +checkedOptions[key];\n\t\t\t\t\t\tcheckedOptions[key] = key === 'items' ? this._validateItems(checkedOptions[key], checkedOptions.skip_validateItems) : checkedOptions[key];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcheckedOptions[key] = setRightOption(mockedTypes[key], key);\n\t\t\t\t\t}\n\t\t\t\t} else if (mockedTypes[key] === 'boolean' && typeof checkedOptions[key] !== 'boolean') {\n\t\t\t\t\tcheckedOptions[key] = setRightOption(mockedTypes[key], key);\n\t\t\t\t} else if (mockedTypes[key] === 'number|boolean' && !this._isNumberOrBoolean(checkedOptions[key])) {\n\t\t\t\t\tcheckedOptions[key] = setRightOption(mockedTypes[key], key);\n\t\t\t\t} else if (mockedTypes[key] === 'number|string' && !this._isNumberOrString(checkedOptions[key])) {\n\t\t\t\t\tcheckedOptions[key] = setRightOption(mockedTypes[key], key);\n\t\t\t\t} else if (mockedTypes[key] === 'string|boolean' && !this._isStringOrBoolean(checkedOptions[key])) {\n\t\t\t\t\tcheckedOptions[key] = setRightOption(mockedTypes[key], key);\n\t\t\t\t} else if (mockedTypes[key] === 'string[]') {\n\t\t\t\t\tif (Array.isArray(checkedOptions[key])) {\n\t\t\t\t\t\tlet isString = false;\n\t\t\t\t\t\tcheckedOptions[key].forEach(element => {\n\t\t\t\t\t\t\tisString = typeof element === 'string' ? true : false;\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (!isString) { checkedOptions[key] = setRightOption(mockedTypes[key], key) };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcheckedOptions[key] = setRightOption(mockedTypes[key], key);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn checkedOptions;\n\t}\n\n\t/**\n\t * Checks the option `items` set by user and if it bigger than number of slides, the function returns number of slides\n\t * @param items option items set by user\n\t * @param skip_validateItems option `skip_validateItems` set by user\n\t * @returns right number of items\n\t */\n\tprivate _validateItems(items: number, skip_validateItems: boolean): number {\n\t\tlet result: number = items;\n\t\tif (items > this._items.length) {\n\t\t\tif (skip_validateItems) {\n\t\t\t\tthis.logger.log('The option \\'items\\' in your options is bigger than the number of slides. The navigation got disabled');\n\t\t\t} else {\n\t\t\t\tresult = this._items.length;\n\t\t\t\tthis.logger.log('The option \\'items\\' in your options is bigger than the number of slides. This option is updated to the current number of slides and the navigation got disabled');\n\t\t\t}\n\t\t} else {\n\t\t\tif (items === this._items.length && (this.settings.dots || this.settings.nav)) {\n\t\t\t\tthis.logger.log('Option \\'items\\' in your options is equal to the number of slides. So the navigation got disabled');\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Set current width of carousel\n\t * @param width width of carousel Window\n\t */\n\tsetCarouselWidth(width: number) {\n\t\tthis._width = width;\n\t}\n\n\t/**\n\t * Setups the current settings.\n\t * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?\n\t * @todo Support for media queries by using `matchMedia` would be nice.\n\t * @param carouselWidth width of carousel\n\t * @param slides array of slides\n\t * @param options options set by user\n\t */\n\tsetup(carouselWidth: number, slides: CarouselSlideDirective[], options: OwlOptions) {\n\t\tthis.setCarouselWidth(carouselWidth);\n\t\tthis.setItems(slides);\n\t\tthis._defineSlidesData();\n\t\tthis.setOptions(options);\n\n\t\tthis.settings = { ...this._options };\n\n\t\tthis.setOptionsForViewport();\n\n\t\tthis._trigger('change', { property: { name: 'settings', value: this.settings } });\n\t\tthis.invalidate('settings'); // must be call of this function;\n\t\tthis._trigger('changed', { property: { name: 'settings', value: this.settings } });\n\t}\n\n\t/**\n\t * Set options for current viewport\n\t */\n\tsetOptionsForViewport() {\n\t\tconst viewport = this._width,\n\t\t\toverwrites = this._options.responsive;\n\t\tlet match = -1;\n\n\t\tif (!Object.keys(overwrites).length) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!viewport) {\n\t\t\tthis.settings.items = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const key in overwrites) {\n\t\t\tif (overwrites.hasOwnProperty(key)) {\n\t\t\t\tif (+key <= viewport && +key > match) {\n\t\t\t\t\tmatch = Number(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.settings = { ...this._options, ...overwrites[match], items: (overwrites[match] && overwrites[match].items) ? this._validateItems(overwrites[match].items, this._options.skip_validateItems) : this._options.items };\n\t\t// if (typeof this.settings.stagePadding === 'function') {\n\t\t// \tthis.settings.stagePadding = this.settings.stagePadding();\n\t\t// }\n\t\tdelete this.settings.responsive;\n\t\tthis.owlDOMData.isResponsive = true;\n\t\tthis.owlDOMData.isMouseDragable = this.settings.mouseDrag;\n\t\tthis.owlDOMData.isTouchDragable = this.settings.touchDrag;\n\n\t\tconst mergers = [];\n\t\tthis._items.forEach(item => {\n\t\t\tconst mergeN: number = this.settings.merge ? item.dataMerge : 1;\n\t\t\tmergers.push(mergeN);\n\t\t});\n\t\tthis._mergers = mergers;\n\n\t\tthis._breakpoint = match;\n\n\t\tthis.invalidate('settings');\n\t}\n\n\t/**\n\t * Initializes the carousel.\n\t * @param slides array of CarouselSlideDirective\n\t */\n\tinitialize(slides: CarouselSlideDirective[]) {\n\t\tthis.enter('initializing');\n\t\t// this.trigger('initialize');\n\n\t\tthis.owlDOMData.rtl = this.settings.rtl;\n\n\t\tif (this._mergers.length) {\n\t\t\tthis._mergers = [];\n\t\t}\n\n\t\tslides.forEach(item => {\n\t\t\tconst mergeN: number = this.settings.merge ? item.dataMerge : 1;\n\t\t\tthis._mergers.push(mergeN);\n\t\t});\n\t\tthis._clones = [];\n\n\t\tthis.reset(this._isNumeric(this.settings.startPosition) ? +this.settings.startPosition : 0);\n\n\t\tthis.invalidate('items');\n\t\tthis.refresh();\n\n\t\tthis.owlDOMData.isLoaded = true;\n\t\tthis.owlDOMData.isMouseDragable = this.settings.mouseDrag;\n\t\tthis.owlDOMData.isTouchDragable = this.settings.touchDrag;\n\n\t\tthis.sendChanges();\n\n\t\tthis.leave('initializing');\n\t\tthis._trigger('initialized');\n\t};\n\n\t/**\n\t * Sends all data needed for View\n\t */\n\tsendChanges() {\n\t\tthis._viewSettingsShipper$.next({\n\t\t\towlDOMData: this.owlDOMData,\n\t\t\tstageData: this.stageData,\n\t\t\tslidesData: this.slidesData,\n\t\t\tnavData: this.navData,\n\t\t\tdotsData: this.dotsData\n\t\t});\n\t}\n\n\n\t/**\n\t * Updates option logic if necessery\n\t */\n\tprivate _optionsLogic() {\n\t\tif (this.settings.autoWidth) {\n\t\t\tthis.settings.stagePadding = 0;\n\t\t\tthis.settings.merge = false;\n\t\t}\n\t}\n\n\t/**\n\t * Updates the view\n\t */\n\tupdate() {\n\t\tlet i = 0;\n\t\tconst n = this._pipe.length,\n\t\t\tfilter = item => this._invalidated[item],\n\t\t\tcache = {};\n\n\t\twhile (i < n) {\n\t\t\tconst filteredPipe = this._pipe[i].filter.filter(filter);\n\t\t\tif (this._invalidated.all || filteredPipe.length > 0) {\n\t\t\t\tthis._pipe[i].run(cache);\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t\tthis.slidesData.forEach(slide => slide.classes = this.setCurSlideClasses(slide));\n\t\tthis.sendChanges();\n\n\t\tthis._invalidated = {};\n\n\t\tif (!this.is('valid')) {\n\t\t\tthis.enter('valid');\n\t\t}\n\t}\n\n\t/**\n\t * Gets the width of the view.\n\t * @param [dimension=Width.Default] The dimension to return\n\t * @returns The width of the view in pixel.\n\t */\n\twidth(dimension?: Width): number {\n\t\tdimension = dimension || Width.Default;\n\t\tswitch (dimension) {\n\t\t\tcase Width.Inner:\n\t\t\tcase Width.Outer:\n\t\t\t\treturn this._width;\n\t\t\tdefault:\n\t\t\t\treturn this._width - this.settings.stagePadding * 2 + this.settings.margin;\n\t\t}\n\t}\n\n\t/**\n\t * Refreshes the carousel primarily for adaptive purposes.\n\t */\n\trefresh() {\n\t\tthis.enter('refreshing');\n\t\tthis._trigger('refresh');\n\t\tthis._defineSlidesData();\n\t\tthis.setOptionsForViewport();\n\n\t\tthis._optionsLogic();\n\n\t\t// this.$element.addClass(this.options.refreshClass);\n\n\t\tthis.update();\n\n\t\t// this.$element.removeClass(this.options.refreshClass);\n\n\t\tthis.leave('refreshing');\n\t\tthis._trigger('refreshed');\n\t}\n\n\t/**\n\t * Checks window `resize` event.\n\t * @param curWidth width of .owl-carousel\n\t */\n\tonResize(curWidth: number) {\n\t\tif (!this._items.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.setCarouselWidth(curWidth);\n\n\t\tthis.enter('resizing');\n\n\t\t// if (this.trigger('resize').isDefaultPrevented()) {\n\t\t// \tthis.leave('resizing');\n\t\t// \treturn false;\n\t\t// }\n\t\tthis._trigger('resize');\n\t\tthis.invalidate('width');\n\n\t\tthis.refresh();\n\n\t\tthis.leave('resizing');\n\t\tthis._trigger('resized');\n\t}\n\n\t/**\n\t * Prepares data for dragging carousel. It starts after firing `touchstart` and `mousedown` events.\n\t * @todo Horizontal swipe threshold as option\n\t * @todo #261\n\t * @param event - The event arguments.\n\t * @returns stage - object with 'x' and 'y' coordinates of .owl-stage\n\t */\n\tprepareDragging(event: any): Coords {\n\t\tlet stage: Coords = null,\n\t\t\ttransformArr: string[];\n\n\t\t// could be 5 commented lines below; However there's stage transform in stageData and in updates after each move of stage\n\t\t// stage = getComputedStyle(this.el.nativeElement).transform.replace(/.*\\(|\\)| /g, '').split(',');\n\t\t// stage = {\n\t\t// x: stage[stage.length === 16 ? 12 : 4],\n\t\t// y: stage[stage.length === 16 ? 13 : 5]\n\t\t// };\n\n\t\ttransformArr = this.stageData.transform.replace(/.*\\(|\\)| |[^,-\\d]\\w|\\)/g, '').split(',');\n\t\tstage = {\n\t\t\tx: +transformArr[0],\n\t\t\ty: +transformArr[1]\n\t\t};\n\n\t\tif (this.is('animating')) {\n\t\t\tthis.invalidate('position');\n\t\t}\n\n\t\tif (event.type === 'mousedown') {\n\t\t\tthis.owlDOMData.isGrab = true;\n\t\t}\n\n\t\tthis.speed(0);\n\t\treturn stage;\n\t}\n\n\t/**\n\t * Enters into a 'dragging' state\n\t */\n\tenterDragging() {\n\t\tthis.enter('dragging');\n\t\tthis._trigger('drag');\n\t}\n\n\t/**\n\t * Defines new coords for .owl-stage while dragging it\n\t * @todo #261\n\t * @param event the event arguments.\n\t * @param dragData initial data got after starting dragging\n\t * @returns coords or false\n\t */\n\tdefineNewCoordsDrag(event: any, dragData: any): boolean | Coords {\n\t\tlet minimum = null,\n\t\t\tmaximum = null,\n\t\t\tpull = null;\n\t\tconst delta = this.difference(dragData.pointer, this.pointer(event)),\n\t\t\tstage = this.difference(dragData.stage.start, delta);\n\n\t\tif (!this.is('dragging')) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.settings.loop) {\n\t\t\tminimum = this.coordinates(this.minimum());\n\t\t\tmaximum = +this.coordinates(this.maximum() + 1) - minimum;\n\t\t\tstage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;\n\t\t} else {\n\t\t\tminimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());\n\t\t\tmaximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());\n\t\t\tpull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;\n\t\t\tstage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);\n\t\t}\n\n\t\treturn stage;\n\t}\n\n\t/**\n\t * Finishes dragging of carousel when `touchend` and `mouseup` events fire.\n\t * @todo #261\n\t * @todo Threshold for click event\n\t * @param event the event arguments.\n\t * @param dragObj the object with dragging settings and states\n\t * @param clickAttacher function which attaches click handler to slide or its children elements in order to prevent event bubling\n\t */\n\tfinishDragging(event: any, dragObj: any, clickAttacher: () => void) {\n\t\tconst directions = ['right', 'left'],\n\t\t\tdelta = this.difference(dragObj.pointer, this.pointer(event)),\n\t\t\tstage = dragObj.stage.current,\n\t\t\tdirection = directions[+(this.settings.rtl ? delta.x < +this.settings.rtl : delta.x > +this.settings.rtl)];\n\t\tlet currentSlideI: number, current: number, newCurrent: number;\n\n\t\tif (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {\n\t\t\tthis.speed(+this.settings.dragEndSpeed || this.settings.smartSpeed);\n\t\t\tcurrentSlideI = this.closest(stage.x, delta.x !== 0 ? direction : dragObj.direction);\n\t\t\tcurrent = this.current();\n\t\t\tnewCurrent = this.current(currentSlideI === -1 ? undefined : currentSlideI);\n\n\t\t\tif (current !== newCurrent) {\n\t\t\t\tthis.invalidate('position');\n\t\t\t\tthis.update();\n\t\t\t}\n\n\t\t\tdragObj.direction = direction;\n\n\t\t\tif (Math.abs(delta.x) > 3 || new Date().getTime() - dragObj.time > 300) {\n\t\t\t\tclickAttacher();\n\t\t\t}\n\t\t}\n\t\tif (!this.is('dragging')) {\n\t\t\treturn;\n\t\t}\n\t\tthis.leave('dragging');\n\t\tthis._trigger('dragged')\n\t}\n\n\t/**\n\t * Gets absolute position of the closest item for a coordinate.\n\t * @todo Setting `freeDrag` makes `closest` not reusable. See #165.\n\t * @param coordinate The coordinate in pixel.\n\t * @param direction The direction to check for the closest item. Ether `left` or `right`.\n\t * @returns The absolute position of the closest item.\n\t */\n\tclosest(coordinate: number, direction: string): number {\n\t\tconst pull = 30,\n\t\t\twidth = this.width();\n\t\tlet coordinates: number[] = this.coordinates() as number[],\n\t\t\tposition = -1;\n\n\t\tif (this.settings.center) {\n\t\t\tcoordinates = coordinates.map(item => {\n\t\t\t\tif (item === 0) {\n\t\t\t\t\titem += 0.000001;\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t})\n\t\t}\n\n\t\t// option 'freeDrag' doesn't have realization and using it here creates problem:\n\t\t// variable 'position' stays unchanged (it equals -1 at the begging) and thus method returns -1\n\t\t// Returning value is consumed by method current(), which taking -1 as argument calculates the index of new current slide\n\t\t// In case of having 5 slides ans 'loop=false; calling 'current(-1)' sets props '_current' as 4. Just last slide remains visible instead of 3 last slides.\n\n\t\t// if (!this.settings.freeDrag) {\n\t\t// check closest item\n\t\tfor (let i = 0; i < coordinates.length; i++) {\n\n\t\t\tif (direction === 'left' && coordinate > coordinates[i] - pull && coordinate < coordinates[i] + pull) {\n\t\t\t\tposition = i;\n\t\t\t\t// on a right pull, check on previous index\n\t\t\t\t// to do so, subtract width from value and set position = index + 1\n\t\t\t} else if (direction === 'right' && coordinate > coordinates[i] - width - pull && coordinate < coordinates[i] - width + pull) {\n\t\t\t\tposition = i + 1;\n\t\t\t} else if (this._op(coordinate, '<', coordinates[i])\n\t\t\t\t&& this._op(coordinate, '>', coordinates[i + 1] || coordinates[i] - width)) {\n\t\t\t\tposition = direction === 'left' ? i + 1 : i;\n\t\t\t} else if (direction === null && coordinate > coordinates[i] - pull && coordinate < coordinates[i] + pull) {\n\t\t\t\tposition = i;\n\t\t\t}\n\n\t\t\tif (position !== -1) { break };\n\t\t}\n\t\t// }\n\n\t\tif (!this.settings.loop) {\n\t\t\t// non loop boundries\n\t\t\tif (this._op(coordinate, '>', coordinates[this.minimum()])) {\n\t\t\t\tposition = coordinate = this.minimum();\n\t\t\t} else if (this._op(coordinate, '<', coordinates[this.maximum()])) {\n\t\t\t\tposition = coordinate = this.maximum();\n\t\t\t}\n\t\t}\n\n\t\treturn position;\n\t}\n\n\t/**\n\t * Animates the stage.\n\t * @todo #270\n\t * @param coordinate The coordinate in pixels.\n\t */\n\tanimate(coordinate: number | number[]) {\n\t\tconst animate = this.speed() > 0;\n\n\t\tif (this.is('animating')) {\n\t\t\tthis.onTransitionEnd();\n\t\t}\n\n\t\tif (animate) {\n\t\t\tthis.enter('animating');\n\t\t\tthis._trigger('translate');\n\t\t}\n\n\t\tthis.stageData.transform = 'translate3d(' + coordinate + 'px,0px,0px)';\n\t\tthis.stageData.transition = (this.speed() / 1000) + 's' + (\n\t\t\tthis.settings.slideTransition ? ' ' + this.settings.slideTransition : ''\n\t\t);\n\n\t\t// also there was transition by means of JQuery.animate or css-changing property left\n\t}\n\n\t/**\n\t * Checks whether the carousel is in a specific state or not.\n\t * @param state The state to check.\n\t * @returns The flag which indicates if the carousel is busy.\n\t */\n\tis(state: string): boolean {\n\t\treturn this._states.current[state] && this._states.current[state] > 0;\n\t};\n\n\t/**\n\t * Sets the absolute position of the current item.\n\t * @param position The new absolute position or nothing to leave it unchanged.\n\t * @returns The absolute position of the current item.\n\t */\n\tcurrent(position?: number): number {\n\t\tif (position === undefined) {\n\t\t\treturn this._current;\n\t\t}\n\n\t\tif (this._items.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tposition = this.normalize(position);\n\n\t\tif (this._current !== position) {\n\t\t\tconst event = this._trigger('change', { property: { name: 'position', value: position } });\n\n\t\t\t// if (event.data !== undefined) {\n\t\t\t// \tposition = this.normalize(event.data);\n\t\t\t// }\n\n\t\t\tthis._current = position;\n\n\t\t\tthis.invalidate('position');\n\t\t\tthis._trigger('changed', { property: { name: 'position', value: this._current } });\n\t\t}\n\n\t\treturn this._current;\n\t}\n\n\t/**\n\t * Invalidates the given part of the update routine.\n\t * @param part The part to invalidate.\n\t * @returns The invalidated parts.\n\t */\n\tinvalidate(part: string): string[] {\n\t\tif (typeof part === 'string') {\n\t\t\tthis._invalidated[part] = true;\n\t\t\tif (this.is('valid')) { this.leave('valid'); }\n\t\t}\n\t\treturn Object.keys(this._invalidated);\n\t};\n\n\t/**\n\t * Resets the absolute position of the current item.\n\t * @param position the absolute position of the new item.\n\t */\n\treset(position: number) {\n\t\tposition = this.normalize(position);\n\n\t\tif (position === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._speed = 0;\n\t\tthis._current = position;\n\n\t\tthis._suppress(['translate', 'translated']);\n\n\t\tthis.animate(this.coordinates(position));\n\n\t\tthis._release(['translate', 'translated']);\n\t}\n\n\t/**\n\t * Normalizes an absolute or a relative position of an item.\n\t * @param position The absolute or relative position to normalize.\n\t * @param relative Whether the given position is relative or not.\n\t * @returns The normalized position.\n\t */\n\tnormalize(position: number, relative?: boolean): number {\n\t\tconst n = this._items.length,\n\t\t\tm = relative ? 0 : this._clones.length;\n\n\t\tif (!this._isNumeric(position) || n < 1) {\n\t\t\tposition = undefined;\n\t\t} else if (position < 0 || position >= n + m) {\n\t\t\tposition = ((position - m / 2) % n + n) % n + m / 2;\n\t\t}\n\n\t\treturn position;\n\t}\n\n\t/**\n\t * Converts an absolute position of an item into a relative one.\n\t * @param position The absolute position to convert.\n\t * @returns The converted position.\n\t */\n\trelative(position: number): number {\n\t\tposition -= this._clones.length / 2;\n\t\treturn this.normalize(position, true);\n\t}\n\n\t/**\n\t * Gets the maximum position for the current item.\n\t * @param relative Whether to return an absolute position or a relative position.\n\t * @returns number of maximum position\n\t */\n\tmaximum(relative: boolean = false): number {\n\t\tconst settings = this.settings;\n\t\tlet maximum = this._coordinates.length,\n\t\t\titerator,\n\t\t\treciprocalItemsWidth,\n\t\t\telementWidth;\n\n\t\tif (settings.loop) {\n\t\t\tmaximum = this._clones.length / 2 + this._items.length - 1;\n\t\t} else if (settings.autoWidth || settings.merge) {\n\t\t\titerator = this._items.length;\n\t\t\treciprocalItemsWidth = this.slidesData[--iterator].width;\n\t\t\telementWidth = this._width;\n\t\t\twhile (iterator-- > 0) {\n\t\t\t\t// it could be use this._items instead of this.slidesData;\n\t\t\t\treciprocalItemsWidth += +this.slidesData[iterator].width + this.settings.margin;\n\t\t\t\tif (reciprocalItemsWidth > elementWidth) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmaximum = iterator + 1;\n\t\t} else if (settings.center) {\n\t\t\tmaximum = this._items.length - 1;\n\t\t} else {\n\t\t\tmaximum = this._items.length - settings.items;\n\t\t}\n\n\t\tif (relative) {\n\t\t\tmaximum -= this._clones.length / 2;\n\t\t}\n\n\t\treturn Math.max(maximum, 0);\n\t}\n\n\t/**\n\t * Gets the minimum position for the current item.\n\t * @param relative Whether to return an absolute position or a relative position.\n\t * @returns number of minimum position\n\t */\n\tminimum(relative: boolean = false): number {\n\t\treturn relative ? 0 : this._clones.length / 2;\n\t}\n\n\t/**\n\t * Gets an item at the specified relative position.\n\t * @param position The relative position of the item.\n\t * @returns The item at the given position or all items if no position was given.\n\t */\n\titems(position?: number): CarouselSlideDirective[] {\n\t\tif (position === undefined) {\n\t\t\treturn this._items.slice();\n\t\t}\n\n\t\tposition = this.normalize(position, true);\n\t\treturn [this._items[position]];\n\t}\n\n\t/**\n\t * Gets an item at the specified relative position.\n\t * @param position The relative position of the item.\n\t * @returns The item at the given position or all items if no position was given.\n\t */\n\tmergers(position: number): number | number[] {\n\t\tif (position === undefined) {\n\t\t\treturn this._mergers.slice();\n\t\t}\n\n\t\tposition = this.normalize(position, true);\n\t\treturn this._mergers[position];\n\t}\n\n\t/**\n\t * Gets the absolute positions of clones for an item.\n\t * @param position The relative position of the item.\n\t * @returns The absolute positions of clones for the item or all if no position was given.\n\t */\n\tclones(position?: number): number[] {\n\t\tconst odd = this._clones.length / 2,\n\t\t\teven = odd + this._items.length,\n\t\t\tmap = index => index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2;\n\n\t\tif (position === undefined) {\n\t\t\treturn this._clones.map((v, i) => map(i));\n\t\t}\n\n\t\treturn this._clones.map((v, i) => v === position ? map(i) : null).filter(item => item);\n\t}\n\n\t/**\n\t * Sets the current animation speed.\n\t * @param speed The animation speed in milliseconds or nothing to leave it unchanged.\n\t * @returns The current animation speed in milliseconds.\n\t */\n\tspeed(speed?: number): number {\n\t\tif (speed !== undefined) {\n\t\t\tthis._speed = speed;\n\t\t}\n\n\t\treturn this._speed;\n\t}\n\n\t/**\n\t * Gets the coordinate of an item.\n\t * @todo The name of this method is missleanding.\n\t * @param position The absolute position of the item within `minimum()` and `maximum()`.\n\t * @returns The coordinate of the item in pixel or all coordinates.\n\t */\n\tcoordinates(position?: number): number | number[] {\n\t\tlet multiplier = 1,\n\t\t\tnewPosition = position - 1,\n\t\t\tcoordinate,\n\t\t\tresult: number[];\n\n\t\tif (position === undefined) {\n\t\t\tresult = this._coordinates.map((item, index) => {\n\t\t\t\treturn this.coordinates(index) as number;\n\t\t\t});\n\t\t\treturn result;\n\t\t}\n\n\t\tif (this.settings.center) {\n\t\t\tif (this.settings.rtl) {\n\t\t\t\tmultiplier = -1;\n\t\t\t\tnewPosition = position + 1;\n\t\t\t}\n\n\t\t\tcoordinate = this._coordinates[position];\n\t\t\tcoordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier;\n\t\t} else {\n\t\t\tcoordinate = this._coordinates[newPosition] || 0;\n\t\t}\n\n\t\tcoordinate = Math.ceil(coordinate);\n\n\t\treturn coordinate;\n\t}\n\n\t/**\n\t * Calculates the speed for a translation.\n\t * @param from The absolute position of the start item.\n\t * @param to The absolute position of the target item.\n\t * @param factor [factor=undefined] - The time factor in milliseconds.\n\t * @returns The time in milliseconds for the translation.\n\t */\n\tprivate _duration(from: number, to: number, factor?: number | boolean): number {\n\t\tif (factor === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((+factor || this.settings.smartSpeed));\n\t}\n\n\t/**\n\t * Slides to the specified item.\n\t * @param position The position of the item.\n\t * @param speed The time in milliseconds for the transition.\n\t */\n\tto(position: number, speed: number | boolean) {\n\t\tlet current = this.current(),\n\t\t\trevert = null,\n\t\t\tdistance = position - this.relative(current),\n\t\t\tmaximum = this.maximum(),\n\t\t\tdelayForLoop = 0;\n\t\tconst direction = +(distance > 0) - +(distance < 0),\n\t\t\titems = this._items.length,\n\t\t\tminimum = this.minimum();\n\n\t\tif (this.settings.loop) {\n\t\t\tif (!this.settings.rewind && Math.abs(distance) > items / 2) {\n\t\t\t\tdistance += direction * -1 * items;\n\t\t\t}\n\n\t\t\tposition = current + distance;\n\t\t\trevert = ((position - minimum) % items + items) % items + minimum;\n\n\t\t\tif (revert !== position && revert - distance <= maximum && revert - distance > 0) {\n\t\t\t\tcurrent = revert - distance;\n\t\t\t\tposition = revert;\n\t\t\t\tdelayForLoop = 30;\n\t\t\t\tthis.reset(current);\n\t\t\t\tthis.sendChanges();\n\t\t\t}\n\t\t} else if (this.settings.rewind) {\n\t\t\tmaximum += 1;\n\t\t\tposition = (position % maximum + maximum) % maximum;\n\t\t} else {\n\t\t\tposition = Math.max(minimum, Math.min(maximum, position));\n\t\t}\n\n\t\tsetTimeout(() => {\n\t\t\tthis.speed(this._duration(current, position, speed));\n\t\t\tthis.current(position);\n\n\t\t\tthis.update();\n\t\t}, delayForLoop);\n\n\t}\n\n\t/**\n\t * Slides to the next item.\n\t * @param speed The time in milliseconds for the transition.\n\t */\n\tnext(speed: number | boolean) {\n\t\tspeed = speed || false;\n\t\tthis.to(this.relative(this.current()) + 1, speed);\n\t}\n\n\t/**\n\t * Slides to the previous item.\n\t * @param speed The time in milliseconds for the transition.\n\t */\n\tprev(speed: number | boolean) {\n\t\tspeed = speed || false;\n\t\tthis.to(this.relative(this.current()) - 1, speed);\n\t}\n\n\t/**\n\t * Handles the end of an animation.\n\t * @param event - The event arguments.\n\t */\n\tonTransitionEnd(event?: any) {\n\t\t// if css2 animation then event object is undefined\n\t\tif (event !== undefined) {\n\t\t\t// event.stopPropagation();\n\n\t\t\t// // Catch only owl-stage transitionEnd event\n\t\t\t// if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)\t) {\n\t\t\t// \treturn false;\n\t\t\t// }\n\t\t\treturn false;\n\t\t}\n\t\tthis.leave('animating');\n\t\tthis._trigger('translated');\n\t}\n\n\t/**\n\t * Gets viewport width.\n\t * @returns - The width in pixel.\n\t */\n\tprivate _viewport(): number {\n\t\tlet width;\n\t\tif (this._width) {\n\t\t\twidth = this._width;\n\t\t} else {\n\t\t\tthis.logger.log('Can not detect viewport width.');\n\t\t}\n\t\treturn width;\n\t}\n\n\t/**\n\t * Sets _items\n\t * @param content The list of slides put into CarouselSlideDirectives.\n\t */\n\tsetItems(content: CarouselSlideDirective[]) {\n\t\tthis._items = content;\n\t}\n\n\t/**\n\t * Sets slidesData using this._items\n