COMPONENT

C-SLIDER

Demo Section

Each variation will be presented in the following sections.

Default Slider

test
test
test
test
test
test
test
test

    Multiple items defined by breakpoints

    By providing 'visibleItems' you can define the visible active slides per breakpoint.

    test
    test
    test
    test
    test
    test
    test
    test

      Multiple items, grouped pagination and custom slide number

      By providing 'groupPaginationItems' you can group the pagination items. Furthermore you can modify the number of elements you want to slide to the left or right by using 'slideByItemNumber'.

      test
      test
      test
      test
      test
      test
      test
      test

        Slider with enabled infinite option

        This means that the first and last elements get cloned and appended to the slide items. Please be aware of that you can not use this option in combination with multiple active slide elements.

        test
        test
        test
        test
        test
        test
        test
        test

          Slider with overflow area

          By providing 'sliderOverflow' you can display all other items next to the active slide(s) as well.

          test
          test
          test
          test
          test
          test
          test
          test

            Slider with autoPlay option

            The autoPlay option gives you the possibility to cycle through your slides automatically by a defined interval. You need to make sure to enable the infinite option. On hover the sliding stops.

            test
            test
            test
            test
            test
            test
            test
            test

              Technical Details

              Bower versionGitter Chat

              Slider

              Description

              The component represents a simple but powerful slider.

              The slider module is a component for cycling through elements, like a carousel or slideshow. It allows users to swipe on touch-enabled devices.


              Requirements

              • Veams >= v5.0.0 - Veams Framework.

              Installation

              Installation with Veams

              veams install vc slider

              Installation with Bower

              bower install veams-component-slider --save


              Fields

              c-slider.hbs

              The partial is a wrapWith partial.

              Settings

              • settings.sliderContextClass {String} [default] - Context class of component.
              • settings.sliderClasses {String} - Modifier classes for component.
              • settings.sliderJsOptions {Object} - JavaScript options which gets stringified.
              • settings.sliderInnerFullWidth {Boolean} [false] - Delete the class .is-container from .slider__content.
              • settings.sliderHidePagination {Boolean} [false] - Hide the pagination when set to true.

              c-slider__controls.hbs

              Content

              • content.sliderButtons {Object} - Contains the controls content. When the object is not defined, the controls will not be printed out.
              • content.sliderButtons.prev {String} - Define the button text for the previous button.
              • content.sliderButtons.next {String} - Define the button text for the next button.

              c-slider__list.hbs

              The partial is a wrapWith partial.

              Settings

              • settings.sliderOverflow {Boolean} - Set this option to true if you want to add the class .is-overflow which gives you the possibility to show all hidden items next to the active element(s).

              c-slider__item.hbs

              The partial is a wrapWith partial.


              JavaScript Options

              The module gives you the possibility to override default options:

              • activeClass {String} [‘is-active’] - Class for the active slide.
              • actions {String} [’[data-js-item=“slider-actions”]’] - Actions wrapper element in the component.
              • autoPlay {Boolean} [false] - Enable autoplay option of the slider.
              • autoPlayInterval {Number} [3000] - Autoplay speed in milliseconds.
              • cloneClass {String} [‘is-cloned’] - For the infinite slider the last and first element get cloned. The cloning class can be overriden.
              • disablePagination {Boolean} [false] - Disable pagination.
              • enableTouchSwipe {Boolean} [true] - Enable support for swipe gestures on touch devices.
              • groupPaginationItems {Boolean} [true] - Enable the grouping of pagination items.
              • hiddenClass {String} [‘is-hidden’] - The hidden class used by handling the visibility of the slider.
              • infinite {Boolean} [‘is-closed’] - The slider will be set in infinite mode. Can not be used with multiple active slide items.
              • items {String} [’[data-js-item=“slider-item”]’] - Define the slide item element.
              • next {String} [’[data-js-item=“slider-next”]’] - Define the next button element.
              • prev {String} [’[data-js-item=“slider-prev”]’] - Define the prev button element.
              • pagination {String} [’[data-js-item=“slider-pagination”]’] - Define the pagination element in which the pagination items are generated in.
              • paginationItemClass {String} [‘slider__pagination-list-item’] - Class for the generated pagination item.
              • paginationItemJsAtom {String} [‘slider-pagination-item’] - Data attribute for the generated pagination item.
              • paginationList {String} [’[data-js-item=“slider-pagination-list”]’] - Define the pagination list element in which the pagination items are generated in.
              • ribbon {String} [’[data-js-item=“slider-ribbon”]’] - Define the slider ribbon which is holding all slides and gets the full width.
              • pauseOnHover {Boolean} [true] - When autoplay is set you can enable/disable pause on hover.
              • slideByItemNumber {Number} [false] - You can use the option to override the initial slide step which is the number of current visible items.
              • startAtIndex {Number} [0] - Start index for the slider.
              • openIndex {Number} [null] - Index of panel to be opened on init (zero based).
              • visibleItems {Object} [ {‘desktop’: 1, ‘tablet-large’: 1, ‘tablet-small’: 1, ‘mobile-large’: 1, ‘mobile-medium’: 1, ‘mobile-small’: 1} ] - Define how many slide items should be visible on different viewports.
              • wrapper {String} [’[data-js-item=“slider-wrapper”]’] - Define the slider wrapper element.

              Sass Options

              There are multiple global variables which you can change:

              • $slider-darken [10 !default] - Darken value for hover effects.
              • $slider-unresolved-height [300px !default] - Set a fix height when the slider is in unresolved state.
              • $slider-duration [600ms !default] - Slide item animation duration.
              • $slider-ease-method [ease !default] - Slide item animation ease method.
              • $slider-control-bg-color [#a5cfd1 !default] - Background color of control buttons.
              • $slider-pagination-color [#555 !default] - Background color of pagination items.
              • $slider-pagination-color-active [$slider-pagination-color !default] - Active vackground color of pagination items which gets darken by $slider-darken.
              • $slider-pagination-size [15px !default] - Pagination size (width & height).
              • $slider-pagination-border-radius [25% !default] - Border radius of pagination items.
              {
              	"variations": {
              		"simple": {
              			"docs": {
              				"variationName": "Default Slider"
              			},
              			"settings": {
              				"sliderContextClass": "default"
              			},
              			"content": {
              				"sliderButtons": {
              					"next": "Next",
              					"prev": "Previous"
              				}
              			}
              		},
              		"multiple": {
              			"docs": {
              				"variationName": "Multiple items defined by breakpoints",
              				"variationDescription": "By providing 'visibleItems' you can define the visible active slides per breakpoint."
              			},
              			"settings": {
              				"sliderContextClass": "default",
              				"sliderJsOptions": {
              					"visibleItems": {
              						"desktop": 3,
              						"tablet-large": 2,
              						"tablet-small": 2,
              						"mobile-large": 2,
              						"mobile-medium": 1,
              						"mobile-small": 1
              					}
              				}
              			},
              			"content": {
              				"sliderButtons": {
              					"next": "Next",
              					"prev": "Previous"
              				}
              			}
              		},"multipleWithGroupedPagination": {
              			"docs": {
              				"variationName": "Multiple items, grouped pagination and custom slide number",
              				"variationDescription": "By providing 'groupPaginationItems' you can group the pagination items. Furthermore you can modify the number of elements you want to slide to the left or right by using 'slideByItemNumber'."
              			},
              			"settings": {
              				"sliderContextClass": "default",
              				"sliderJsOptions": {
              					"groupPaginationItems": true,
              					"slideByItemNumber": 1,
              					"visibleItems": {
              						"desktop": 3,
              						"tablet-large": 2,
              						"tablet-small": 2,
              						"mobile-large": 2,
              						"mobile-medium": 1,
              						"mobile-small": 1
              					}
              				}
              			},
              			"content": {
              				"sliderButtons": {
              					"next": "Next",
              					"prev": "Previous"
              				}
              			}
              		},
              		"infinite": {
              			"docs": {
              				"variationName": "Slider with enabled infinite option",
              				"variationDescription": "This means that the first and last elements get cloned and appended to the slide items. Please be aware of that you can not use this option in combination with multiple active slide elements."
              			},
              			"settings": {
              				"sliderContextClass": "default",
              				"sliderJsOptions": {
              					"infinite": true
              				}
              			},
              			"content": {
              				"sliderButtons": {
              					"next": "Next",
              					"prev": "Previous"
              				}
              			}
              		},
              		"overflow": {
              			"docs": {
              				"variationName": "Slider with overflow area",
              				"variationDescription": "By providing 'sliderOverflow' you can display all other items next to the active slide(s) as well."
              			},
              			"settings": {
              				"sliderContextClass": "default",
              				"sliderOverflow": true,
              				"sliderJsOptions": {
              					"infinite": true
              				}
              			},
              			"content": {
              				"sliderButtons": {
              					"next": "Next",
              					"prev": "Previous"
              				}
              			}
              		},
              		"autoplay": {
              			"docs": {
              				"variationName": "Slider with autoPlay option",
              				"variationDescription": "The autoPlay option gives you the possibility to cycle through your slides automatically by a defined interval. You need to make sure to enable the infinite option. On hover the sliding stops."
              			},
              			"settings": {
              				"sliderContextClass": "default",
              				"sliderJsOptions": {
              					"infinite": true,
              					"autoPlay": true,
              					"autoPlayInterval": 3500
              				}
              			},
              			"content": {
              				"sliderButtons": {
              					"next": "Next",
              					"prev": "Previous"
              				}
              			}
              		}
              	}
              }
              

              c-slider-usage

              {{! wrapWith START: Slider }}
              {{#wrapWith "c-slider" settings=this.settings content=this.content}}
              	{{! WrapWith START: Slider List }}
              	{{#wrapWith "c-slider__list" settings=this.settings}}
              		{{#times 8}}
              			{{#wrapWith "c-slider__item"}}
              				<img src="https://placehold.it/1920x800" alt="test">
              			{{/wrapWith}}
              		{{/times}}
              	{{/wrapWith}}
              	{{! WrapWith END: Slider List }}
              {{/wrapWith}}
              {{! wrapWith END: Slider}}
              

              c-slider.hbs

              <div class="c-slider{{#if options.settings.sliderContextClass}}--{{options.settings.sliderContextClass}}{{else}}--default{{/if}}{{#if options.settings.sliderContextClass}} {{options.settings.sliderContextClass}}{{/if}}"
                   data-css="c-slider"
                   data-js-module="slider"{{#if options.settings.sliderJsOptions}}
                   data-js-options='{{stringify options.settings.sliderJsOptions}}'{{/if}}>
              
              	{{#with options.content.sliderButtons}}
              		<div class="slider__controls-wrapper" data-js-item="slider-actions">
              			{{> c-slider__controls }}
              		</div>
              	{{/with}}
              
              	<div class="slider__content{{#unless options.settings.sliderInnerFullWidth}} is-container{{/unless}}">
              		{{{yield}}}
              	</div>
              
              	{{#unless options.settings.sliderHidePagination}}
              		<div class="slider__pagination-wrapper" data-js-item="slider-pagination">
              			{{> c-slider__pagination }}
              		</div>
              	{{/unless}}
              </div>
              

              c-slider__item.hbs

              <div class="slider__item" data-js-item="slider-item">
              	{{{yield}}}
              </div>
              
              /* ===================================================
              Slider Module
              =================================================== */
              
              /* ---------------------------------------------------
              Global Variables
              --------------------------------------------------- */
              // General
              $slider-darken: 10 !default;
              $slider-unresolved-height: 300px !default;
              // Animation Variables
              $slider-duration: 600ms !default;
              $slider-ease-method: ease !default;
              // Controls
              $slider-control-bg-color: #a5cfd1 !default;
              // Pagination
              $slider-pagination-color: #555 !default;
              $slider-pagination-color-active: $slider-control-bg-color !default;
              $slider-pagination-size: 15px !default;
              $slider-pagination-border-radius: 25% !default;
              
              /* ---------------------------------------------------
              Global Styles
              --------------------------------------------------- */
              
              [data-js-module~="slider"] {
              	clear: both;
              	display: block;
              	position: relative;
              
              	/*
              	Unresolved state
              	----------------------- */
              	&.is-unresolved {
              		.slider__list {
              			height: $slider-unresolved-height;
              			overflow: hidden;
              		}
              
              		.slider__item {
              			opacity: 0;
              		}
              	}
              
              	/*
              	List
              	----------------------- */
              	.slider__list-wrapper {
              		display: block;
              		position: relative;
              		overflow: hidden;
              
              		&.is-overflow {
              			overflow: visible;
              		}
              	}
              
              	.slider__list {
              		left: 0;
              		position: relative;
              		transform: translate3d(0, 0, 0);
              		transition: left $slider-duration $slider-ease-method;
              	}
              
              	.slider__item {
              		@include float;
              
              		position: relative;
              		opacity: 0.3;
              		transition: opacity $slider-duration $slider-ease-method;
              		vertical-align: top;
              
              		&.is-active {
              			opacity: 1;
              		}
              
              		&:first-child {
              			margin-left: 0;
              		}
              	}
              
              	/*
              	Actions
              	----------------------- */
              	.slider__controls-wrapper {
              		@include centering(v);
              
              		width: 100%;
              		z-index: 100;
              	}
              
              	.slider__control {
              		@include reset-btn();
              		@include centering(v);
              
              		background-color: $slider-control-bg-color;
              		position: absolute;
              		padding: 1rem;
              		transition: background-color $slider-duration/4 $slider-ease-method;
              
              		&:hover {
              			cursor: pointer;
              			background-color: darken($slider-control-bg-color, $slider-darken);
              		}
              
              		&.is-previous {
              			left: 0;
              		}
              
              		&.is-next {
              			right: 0;
              		}
              	}
              
              	/*
              	Pagination
              	----------------------- */
              	.slider__pagination-wrapper {
              		@include centering(h);
              
              		bottom: -$slider-pagination-size;
              	}
              
              	.slider__pagination-list {
              		margin: 0;
              		padding: 0;
              	}
              
              	.slider__pagination-list-item {
              		@extend %hidden-text;
              
              		background-color: $slider-pagination-color;
              		border-radius: $slider-pagination-border-radius;
              		display: inline-block;
              		height: $slider-pagination-size;
              		margin: 0 $slider-pagination-size/3;
              		width: $slider-pagination-size;
              		transition: background-color $slider-duration/4 $slider-ease-method;
              
              		&:hover {
              			cursor: pointer;
              			background-color: darken($slider-pagination-color, $slider-darken);
              		}
              
              		&.is-active {
              			background-color: $slider-pagination-color-active;
              		}
              
              		&.is-hidden {
              			display: none;
              		}
              	}
              }
              
              /* ---------------------------------------------------
              Context: Default
              --------------------------------------------------- */
              .c-slider--default {
              	@extend %float;
              }
              

              slider.js

              /**
               * Represents a responsive slider which can be used as ribbon.
               *
               * @module Slider
               * @version v3.0.2
               *
               * @author Sebastian Fitzner
               * @author Andy Gutsche
               */
              
              import { Veams } from 'app';
              import VeamsComponent from 'veams/src/js/common/component';
              import transitionEndEvent from 'veams/src/js/utils/helpers/transition-end-event'
              
              const $ = Veams.$;
              const Helpers = Veams.helpers;
              
              class Slider extends VeamsComponent {
              	/**
              	 * Constructor for our class
              	 *
              	 * @see module.js
              	 *
              	 * @param {Object} obj - Object which is passed to our class
              	 * @param {Object} obj.el - element which will be saved in this.el
              	 * @param {Object} obj.options - options which will be passed in as JSON object
              	 */
              	constructor(obj) {
              		let options = {
              			activeClass: 'is-active', // Active class for slides and pagination items
              			actions: '[data-js-item="slider-actions"]', // Previous Button
              			autoPlay: false, // Enable autoplay
              			autoPlayInterval: 3000, // Autoplay intervall in milliseconds
              			cloneClass: 'is-cloned', // Clone class for cloned items (only used with infinite)
              			disablePagination: false, // Disable pagination display
              			enableTouchSwipe: true, // Enable/Disable swipe support
              			groupPaginationItems: false, // Group the pagination elements (useful for multiple visible items)
              			hiddenClass: 'is-hidden', // hidden class for pagination
              			infinite: false, // Infinite looping (only possible without multiple visible items)
              			items: '[data-js-item="slider-item"]', // Slide Items
              			next: '[data-js-item="slider-next"]', // Next Button
              			prev: '[data-js-item="slider-prev"]', // Previous Button
              			pagination: '[data-js-item="slider-pagination"]', // Pagination
              			paginationItemClass: 'slider__pagination-list-item', // Define your class which we use in our mini tmpl
              			paginationItemJsItem: 'slider-pagination-item', // data-js-item for pagination list item
              			paginationList: '[data-js-item="slider-pagination-list"]', // Pagination List
              			ribbon: '[data-js-item="slider-ribbon"]', // Ribbon element
              			pauseOnHover: true, // Used when options.autoPlay is true
              			slideByItemNumber: false, // Use the option to override the initial slide step
              			startAtIndex: 0, // Start at a different index
              			unresolvedClass: 'is-unresolved', // Unresolved class which gets removed when initialized
              			visibleItems: { // Visible items per viewport
              				'desktop': 1,
              				'tablet-large': 1,
              				'tablet-small': 1,
              				'mobile-large': 1,
              				'mobile-medium': 1,
              				'mobile-small': 1
              			},
              			wrapper: '[data-js-item="slider-wrapper"]' // Wrapper element
              		};
              
              		super(obj, options);
              	}
              
              	/**
              	 * Custom getters and setter
              	 */
              
              	/**
              	 * Get module information
              	 */
              	static get info() {
              		return {
              			version: '3.0.2',
              			vc: true,
              			mod: false
              		};
              	}
              
              	/**
              	 * Get and set visible items.
              	 *
              	 * @param {number} visible - Number of visible items
              	 */
              	get visibles() {
              		return this._numVisible;
              	}
              
              	set visibles(visible) {
              		this._numVisible = visible;
              	}
              
              	/**
              	 * Get and set items length for slider.
              	 *
              	 * @param {number} len - Number of item length
              	 */
              	get itemsLength() {
              		return this._itemLength;
              	}
              
              	set itemsLength(len) {
              		this._itemLength = len;
              	}
              
              	/**
              	 * Get and set the index of slider.
              	 *
              	 * @param {number} idx - index number of slide
              	 */
              	get index() {
              		return this._index;
              	}
              
              	set index(idx) {
              		this._index = idx;
              	}
              
              	/**
              	 * Get paused property.
              	 *
              	 * @param {Boolean} bool - pause state
              	 */
              	get paused() {
              		return this._paused;
              	}
              
              	set paused(bool) {
              		this._paused = bool;
              	}
              
              	/**
              	 * Get autoPlay property.
              	 *
              	 * @param {Boolean} bool - autoplay state
              	 */
              	get autoPlay() {
              		return this._autoPlay;
              	}
              
              	set autoPlay(bool) {
              		this._autoPlay = bool;
              	}
              
              	/**
              	 * Get controls height.
              	 */
              	get controlHeight() {
              		return Helpers.getOuterHeight(this.$prev);
              	}
              
              	/**
              	 * Return the defined option or current visible items
              	 * which will be used for the next and previous slide animation.
              	 */
              	get slideBy() {
              		return this.options.slideByItemNumber || this.visibles;
              	}
              
              	/**
              	 * Get ribbon width.
              	 */
              	get ribbonWidth() {
              		return this.$items.length * (this.thumbWidth);
              	}
              
              	/** =================================================
              	 * EVENTS
              	 * ================================================ */
              
              	/**
              	 * Bind local events to this.$el.
              	 */
              	get events() {
              		return {
              			'click {{this.options.prev}}': 'showPrevElement',
              			'touchstart {{this.options.prev}}': 'showPrevElement',
              			'click {{this.options.next}}': 'showNextElement',
              			'touchstart {{this.options.next}}': 'showNextElement',
              			'click {{this.paginationItemSel}}': 'navigateToElement',
              			'touchstart {{this.paginationItemSel}}': 'navigateToElement'
              		};
              	}
              
              	/**
              	 * Subscribe to global events of Veams or App namespace.
              	 */
              	get subscribe() {
              		return {
              			'{{Veams.EVENTS.resize}}': 'render'
              		};
              	}
              	
              	/**
              	 * Bind all events
              	 */
              	bindEvents() {
              		if (this.autoPlay && this.options.pauseOnHover) {
              			this.registerEvent('{{Veams.EVENTS.mouseenter}}', 'pause');
              			this.registerEvent('{{Veams.EVENTS.mouseleave}}', 'play');
              		}
              	}
              
              	/**
              	 * Unbind all events
              	 */
              	unbindEvents() {
              		// Global Events
              		Veams.Vent.off(Veams.EVENTS.resize);
              
              		// Local Events
              		this.$el.off(Veams.clickHandler);
              	}
              
              	/** =================================================
              	 * STANDARD METHODS
              	 * ================================================= */
              
              	/**
              	 * Initialize the view
              	 */
              	initialize() {
              		this.index = 0;
              		this.$prev = this.$el.find(this.options.prev);
              		this.$next = this.$el.find(this.options.next);
              		this.$items = this.$el.find(this.options.items);
              		this.$initialItems = this.$items;
              		this.$wrapper = this.$el.find(this.options.wrapper);
              		this.$ribbon = this.$el.find(this.options.ribbon);
              		this.startAtIndex = ~~this.options.startAtIndex;
              		this.$lastItem = this.$items.eq(this.$items.length - 1);
              		this.$firstItem = this.$items.eq(0);
              		this.transition = this.$ribbon.css('transition');
              		this.paginationDisabled = this.options.disablePagination || this.$items.length < 2;
              		this.infinite = this.options.infinite && this.$items.length > 1;
              		this.touchSwipeEnabled = false;
              		this.clickHandler = true;
              		this.autoPlay = this.options.autoPlay && this.infinite;
              		this.paginationItemSel = '[data-js-item="' + this.options.paginationItemJsItem + '"]';
              
              
              		if (!this.paginationDisabled) {
              			this.$paginationList = this.$el.find(this.options.paginationList);
              		}
              
              		if (this.options.autoPlay && !this.infinite) {
              			console.warn('Slider: Sorry - option "autoPlay" has no effect while option "infinite" is set to false!');
              		}
              
              		if (this.infinite) {
              
              			for (let item in this.options.visibleItems) {
              				if (this.options.visibleItems.hasOwnProperty(item)) {
              					if (this.options.visibleItems[item] > 1) {
              						console.warn(
              							'Slider: Sorry - option "visibleItems" has no effect while option "infinite" is set to true!');
              						break;
              					}
              				}
              			}
              		}
              	}
              
              	/**
              	 * Renders the view's template to the UI
              	 */
              	render() {
              		if (!Veams.currentMedia) {
              			console.warn('Slider: Veams.currentMedia is necessary to support the slider module!');
              			return;
              		}
              
              		if (this.$clonedLast && this.$clonedFirst) {
              			this.$clonedLast.remove();
              			this.$clonedFirst.remove();
              			this.$items = this.$initialItems;
              		}
              
              		this.visibles = this.infinite ? 1 : this.options.visibleItems[Veams.currentMedia];
              		this.itemsLength = this.$items.length;
              
              		this.handleVisibility();
              
              		if (!this.paginationDisabled) {
              			this.removePagination();
              			this.addPagination();
              		}
              
              		if (this.infinite) {
              			this.infiniteLoop();
              		}
              
              		this.bindTransitions();
              		this.getAndSetDimensions();
              
              		if (Veams.detections.touch && this.options.enableTouchSwipe && !this.touchSwipeEnabled) {
              			this.bindSwipes();
              		}
              
              		if (this.infinite) {
              			this.goToItem(this.startAtIndex + this.visibles);
              		}
              		else {
              			this.goToItem(this.startAtIndex);
              		}
              
              		if (this.autoPlay && this.paused) {
              			this.play();
              		}
              	}
              	
              	/** =================================================
              	 * CUSTOM SLIDER METHODS
              	 * ================================================= */
              	
              	/**
              	 * Bind transition events
              	 *
              	 */
              	bindTransitions() {
              		let onRibbonTransitionEnd = this.onRibbonTransitionEnd.bind(this);
              		let onItemsTransitionEnd = this.onItemsTransitionEnd.bind(this);
              
              		this.$ribbon.on(transitionEndEvent(), onRibbonTransitionEnd);
              		this.$items.on(transitionEndEvent(), onItemsTransitionEnd);
              	}
              
              	/**
              	 * React to transitionend on ribbon
              	 *
              	 * @param {Object} e - Event object.
              	 */
              	onRibbonTransitionEnd(e) {
              		e.stopPropagation();
              
              		if (this.autoPlay && this.paused) {
              
              			if (this.options.pauseOnHover) {
              
              				if (!this.$el.is(':hover')) {
              					this.play();
              				}
              			}
              			else {
              				this.play();
              			}
              		}
              
              		if (this.$clonedFirst && this.$clonedFirst.hasClass(this.options.activeClass)) {
              			this.$clonedFirst.removeClass(this.options.activeClass);
              			this.index = 1;
              
              			this.animateSlide({
              				idx: this.index,
              				animate: false
              			});
              		}
              
              		if (this.$clonedLast && this.$clonedLast.hasClass(this.options.activeClass)) {
              			this.$clonedLast.removeClass(this.options.activeClass);
              			this.index = this.$items.length - this.visibles - 1;
              
              			this.animateSlide({
              				idx: this.index,
              				animate: false
              			});
              		}
              
              		this.clickHandler = true;
              	}
              
              
              	/**
              	 * React to transitionend on items
              	 *
              	 * @param {Object} e - Event object.
              	 */
              	onItemsTransitionEnd(e) {
              		e.stopPropagation();
              	}
              
              	/**
              	 * Clone first and last element
              	 *
              	 */
              	infiniteLoop() {
              		this.$clonedFirst = this.$firstItem.clone(true).addClass(this.options.cloneClass);
              		this.$clonedLast = this.$lastItem.clone(true).addClass(this.options.cloneClass);
              
              		if (this.options.infinite) {
              			this.$clonedFirst.find(this.paginationItemSel).attr('data-index', this.itemsLength);
              			this.$clonedLast.find(this.paginationItemSel).attr('data-index', -1);
              		}
              
              		this.$firstItem.before(this.$clonedLast);
              		this.$lastItem.after(this.$clonedFirst);
              
              		this.$items = $(this.options.items, this.$el);
              	}
              
              	/**
              	 * Animate slide
              	 *
              	 * @param {Object} obj - animation property object.
              	 */
              	animateSlide(obj) {
              		if (!obj.animate) {
              			this.$ribbon.css('transition', 'none');
              		} else {
              			this.$ribbon.css('transition', this.transition);
              		}
              
              		this.$ribbon.css('left', -obj.idx * (this.thumbWidth) + 'px');
              	}
              
              	/**
              	 * Check first/last slide classes
              	 *
              	 */
              	checkSlides() {
              
              		if (this.$clonedFirst.hasClass(this.options.activeClass)) {
              			this.$firstItem.addClass(this.options.activeClass);
              		}
              		if (this.$clonedLast.hasClass(this.options.activeClass)) {
              			this.$lastItem.addClass(this.options.activeClass);
              		}
              	}
              
              	/**
              	 * When items length is 0 we hide this view.
              	 */
              	handleVisibility() {
              		if (this.itemsLength === 0) {
              			this.$el.addClass(this.options.hiddenClass);
              			console.warn('Slider: There is no item we can use in our slider :(');
              		}
              
              		this.$el.css('max-width', 'none');
              	}
              
              	/**
              	 * Empty pagination.
              	 */
              	removePagination() {
              		this.$paginationList.empty();
              	}
              
              	/**
              	 * Add pagination elements with a simple string template and
              	 * save a pagination item reference.
              	 */
              	addPagination() {
              		let tmpl = '';
              		let i = 0;
              		let item = this.options.paginationItemJsItem;
              		let itemClass = this.options.paginationItemClass;
              
              		for (i; i < this.$items.length; i++) {
              			let idx = i + 1;
              			let hiddenClass = '';
              
              			if (this.options.groupPaginationItems) {
              				hiddenClass = i % this.visibles === 0 ? '' : this.options.hiddenClass;
              			}
              
              			tmpl += `
              					<li class="${itemClass} ${hiddenClass}" data-js-item="${item}" data-index="${i}">
              						<strong>${idx}</strong>
              					</li>
              					`;
              		}
              
              		this.$paginationList.append(tmpl);
              		this.$paginationItems = $('[data-js-item="' + this.options.paginationItemJsItem + '"]', this.$el);
              	}
              
              	/**
              	 * Navigate to a specific slide.
              	 *
              	 * @param {object} e - Event object.
              	 * @param {object} currentTarget - Target to which listener was attached.
              	 */
              	navigateToElement(e, currentTarget) {
              		let $currentTarget = currentTarget ? $(currentTarget) : $(e.currentTarget);
              
              		if ($currentTarget.hasClass(this.options.activeClass)) {
              			return;
              		}
              
              		let idx = parseInt($currentTarget.attr('data-index'), 10) || $currentTarget.index();
              
              		if (this.infinite) {
              			idx = idx + this.slideBy;
              		}
              
              		this.goToItem(idx);
              	}
              
              	/**
              	 * Go to the next slide.
              	 *
              	 * @param {object} e - Event object.
              	 * @param {object} currentTarget - Target to which listener was attached.
              	 */
              	showNextElement(e, currentTarget) {
              		let $currentTarget = currentTarget ? $(currentTarget) : $(e.currentTarget);
              
              		if (e && typeof e.preventDefault === 'function') {
              			e.preventDefault();
              		}
              
              		if ($currentTarget.prop('disabled')) {
              			return;
              		}
              
              		if (this.clickHandler) {
              			this.goToItem(this.index + this.slideBy);
              			this.clickHandler = false;
              		}
              	}
              
              	/**
              	 * Go to the previous slide.
              	 *
              	 * @param {object} e - Event object.
              	 * @param {object} currentTarget - Target to which listener was attached.
              	 */
              	showPrevElement(e, currentTarget) {
              		let $currentTarget = currentTarget ? $(currentTarget) : $(e.currentTarget);
              
              		if (e && typeof e.preventDefault === 'function') {
              			e.preventDefault();
              		}
              
              		if ($currentTarget.prop('disabled')) {
              			return;
              		}
              
              		if (this.clickHandler) {
              			this.goToItem(this.index - this.slideBy);
              			this.clickHandler = false;
              		}
              	}
              
              	/**
              	 * Return the direction `next` or `prev`.
              	 *
              	 * @param {number} index - Index of the pagination element.
              	 */
              	getDirection(index) {
              		return index > this.index ? "next" : "prev";
              	}
              
              	/**
              	 * Bind all swipe gestures.
              	 */
              	bindSwipes() {
              
              		if (this.$items.length > this.visibles) {
              			Helpers.detectSwipe(this.el, 75);
              
              			this.$el.on(Veams.EVENTS.swipe, (e) => {
              				let direction = e.detail.direction;
              
              				if (direction === 'left') {
              					this.goToItem(this.index + this.visibles);
              				}
              
              				if (direction === 'right') {
              					this.goToItem(this.index - this.visibles);
              				}
              			});
              
              			this.touchSwipeEnabled = true;
              		}
              	}
              
              	/**
              	 * Enables button
              	 *
              	 * @param {Object} $btn - button element.
              	 */
              	enableBtn($btn) {
              		$btn.removeClass(this.options.hiddenClass);
              		$btn.prop('disabled', false);
              		$btn.removeAttr('aria-disabled');
              	}
              
              	/**
              	 * Disables button
              	 *
              	 * @param {Object} $btn - button element.
              	 */
              	disableBtn($btn) {
              		$btn.addClass(this.options.hiddenClass);
              		$btn.prop('disabled', true);
              		$btn.attr('aria-disabled', true);
              	}
              
              	/**
              	 * Handles the method to go to a specific item.
              	 * Further we handle the class
              	 *
              	 * @param {number} i - Index number.
              	 */
              	goToItem(i) {
              		let maxIndex = this.$items.length - this.visibles;
              
              		if (maxIndex < 0) {
              			maxIndex = 0;
              		}
              
              		if (!this.paused) {
              			this.pause();
              		}
              
              		if (this.infinite) {
              			if (i < 0) {
              				i = maxIndex;
              			} else if (i > maxIndex) {
              				i = 0;
              			}
              		}
              		else {
              			this.enableBtn(this.$prev);
              			this.enableBtn(this.$next);
              
              			if (i < 1) {
              				this.disableBtn(this.$prev);
              
              				if (i < 0) {
              					i = 0;
              				}
              			}
              
              			if (i > maxIndex - 1) {
              				this.disableBtn(this.$next);
              
              				if (i > maxIndex) {
              					i = maxIndex;
              				}
              			}
              		}
              
              		this.animateSlide({
              			idx: i,
              			animate: !this.$el.hasClass(this.options.unresolvedClass)
              		});
              
              		if (this.$el.hasClass(this.options.unresolvedClass)) {
              			this.$el.removeClass(this.options.unresolvedClass);
              		}
              
              		this.index = i;
              
              		this.handleActivity();
              
              		if (this.infinite) {
              			this.checkSlides();
              		}
              	}
              
              	handleActivity() {
              		this.$items.removeClass(this.options.activeClass);
              
              		if (!this.paginationDisabled && this.$paginationItems && this.$paginationItems.length) {
              			this.$paginationItems.removeClass(this.options.activeClass);
              		}
              
              		// If this slider instance isn't infinite
              		if (!this.infinite) {
              			for (let idx = this.index; idx < this.index + this.visibles; idx++) {
              
              				// First set active slide element(s)
              				this.$items
              					.eq(idx)
              					.addClass(this.options.activeClass);
              
              				// Do that also for pagination element(s)
              				if (!this.paginationDisabled) {
              					this.$paginationItems
              						.eq(idx)
              						.addClass(this.options.activeClass);
              				}
              			}
              		}
              		else {
              			for (let idx = this.index - 1; idx < this.index - 1 + this.visibles; idx++) {
              				let slideIdx = idx;
              				this.$items
              					.eq(slideIdx + 1)
              					.addClass(this.options.activeClass);
              
              				if (!this.paginationDisabled) {
              					if (idx >= this.$paginationItems.length) {
              						slideIdx = 0;
              					}
              
              					if (idx < 0) {
              						slideIdx = this.$paginationItems.length - 1;
              					}
              
              					this.$paginationItems
              						.eq(slideIdx)
              						.addClass(this.options.activeClass);
              				}
              			}
              		}
              	}
              
              	/**
              	 * Start autoplay.
              	 */
              	play() {
              		clearInterval(this.autoPlayInterval);
              
              		this.autoPlayInterval = setInterval(() => {
              			this.goToItem(this.index + this.visibles);
              		}, this.options.autoPlayInterval);
              
              		this.paused = false;
              	}
              
              	/**
              	 * Pause autoplay.
              	 */
              	pause() {
              		clearInterval(this.autoPlayInterval);
              		this.paused = true;
              	}
              
              	/**
              	 * Get and set dimensions for our project progress.
              	 */
              	getAndSetDimensions() {
              		this.resetStyles();
              		this.width = this.$wrapper.outerWidth();
              		this.thumbWidth = this.width / this.visibles;
              		this.$wrapper.css('width', this.width + 'px');
              		this.$items.css('width', this.thumbWidth + 'px');
              
              		this.$ribbon.css({
              			width: this.ribbonWidth + 'px'
              		});
              	}
              
              	/**
              	 * Reset width styles
              	 */
              	resetStyles() {
              		this.$wrapper[0].removeAttribute('style');
              		this.$items.removeAttr('style');
              		this.$ribbon.removeAttr('style');
              	}
              }
              
              export default Slider;
              

              Default Slider

              <div class="c-slider--default default" data-css="c-slider" data-js-module="slider">
              	<div class="slider__controls-wrapper" data-js-item="slider-actions">
              		<button class="slider__control is-previous" data-js-item="slider-prev">
              	Previous
              </button>
              		<button class="slider__control is-next" data-js-item="slider-next">
              	Next
              </button> </div>
              	<div class="slider__content is-container">
              		<div class="slider__list-wrapper" data-js-item="slider-wrapper">
              			<div class="slider__list" data-js-item="slider-ribbon">
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              			</div>
              		</div>
              	</div>
              	<div class="slider__pagination-wrapper" data-js-item="slider-pagination">
              		<ol class="slider__pagination-list" data-js-item="slider-pagination-list">
              		</ol>
              	</div>
              </div>

              Multiple items defined by breakpoints

              <div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{&quot;visibleItems&quot;:{&quot;desktop&quot;:3,&quot;tablet-large&quot;:2,&quot;tablet-small&quot;:2,&quot;mobile-large&quot;:2,&quot;mobile-medium&quot;:1,&quot;mobile-small&quot;:1}}'>
              	<div class="slider__controls-wrapper" data-js-item="slider-actions">
              		<button class="slider__control is-previous" data-js-item="slider-prev">
              	Previous
              </button>
              		<button class="slider__control is-next" data-js-item="slider-next">
              	Next
              </button> </div>
              	<div class="slider__content is-container">
              		<div class="slider__list-wrapper" data-js-item="slider-wrapper">
              			<div class="slider__list" data-js-item="slider-ribbon">
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              			</div>
              		</div>
              	</div>
              	<div class="slider__pagination-wrapper" data-js-item="slider-pagination">
              		<ol class="slider__pagination-list" data-js-item="slider-pagination-list">
              		</ol>
              	</div>
              </div>

              Multiple items, grouped pagination and custom slide number

              <div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{&quot;groupPaginationItems&quot;:true,&quot;slideByItemNumber&quot;:1,&quot;visibleItems&quot;:{&quot;desktop&quot;:3,&quot;tablet-large&quot;:2,&quot;tablet-small&quot;:2,&quot;mobile-large&quot;:2,&quot;mobile-medium&quot;:1,&quot;mobile-small&quot;:1}}'>
              	<div class="slider__controls-wrapper" data-js-item="slider-actions">
              		<button class="slider__control is-previous" data-js-item="slider-prev">
              	Previous
              </button>
              		<button class="slider__control is-next" data-js-item="slider-next">
              	Next
              </button> </div>
              	<div class="slider__content is-container">
              		<div class="slider__list-wrapper" data-js-item="slider-wrapper">
              			<div class="slider__list" data-js-item="slider-ribbon">
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              			</div>
              		</div>
              	</div>
              	<div class="slider__pagination-wrapper" data-js-item="slider-pagination">
              		<ol class="slider__pagination-list" data-js-item="slider-pagination-list">
              		</ol>
              	</div>
              </div>

              Slider with enabled infinite option

              <div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{&quot;infinite&quot;:true}'>
              	<div class="slider__controls-wrapper" data-js-item="slider-actions">
              		<button class="slider__control is-previous" data-js-item="slider-prev">
              	Previous
              </button>
              		<button class="slider__control is-next" data-js-item="slider-next">
              	Next
              </button> </div>
              	<div class="slider__content is-container">
              		<div class="slider__list-wrapper" data-js-item="slider-wrapper">
              			<div class="slider__list" data-js-item="slider-ribbon">
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              			</div>
              		</div>
              	</div>
              	<div class="slider__pagination-wrapper" data-js-item="slider-pagination">
              		<ol class="slider__pagination-list" data-js-item="slider-pagination-list">
              		</ol>
              	</div>
              </div>

              Slider with overflow area

              <div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{&quot;infinite&quot;:true}'>
              	<div class="slider__controls-wrapper" data-js-item="slider-actions">
              		<button class="slider__control is-previous" data-js-item="slider-prev">
              	Previous
              </button>
              		<button class="slider__control is-next" data-js-item="slider-next">
              	Next
              </button> </div>
              	<div class="slider__content is-container">
              		<div class="slider__list-wrapper is-overflow" data-js-item="slider-wrapper">
              			<div class="slider__list" data-js-item="slider-ribbon">
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              			</div>
              		</div>
              	</div>
              	<div class="slider__pagination-wrapper" data-js-item="slider-pagination">
              		<ol class="slider__pagination-list" data-js-item="slider-pagination-list">
              		</ol>
              	</div>
              </div>

              Slider with autoPlay option

              <div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{&quot;infinite&quot;:true,&quot;autoPlay&quot;:true,&quot;autoPlayInterval&quot;:3500}'>
              	<div class="slider__controls-wrapper" data-js-item="slider-actions">
              		<button class="slider__control is-previous" data-js-item="slider-prev">
              	Previous
              </button>
              		<button class="slider__control is-next" data-js-item="slider-next">
              	Next
              </button> </div>
              	<div class="slider__content is-container">
              		<div class="slider__list-wrapper" data-js-item="slider-wrapper">
              			<div class="slider__list" data-js-item="slider-ribbon">
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              				<div class="slider__item" data-js-item="slider-item">
              					<img src="https://placehold.it/1920x800" alt="test">
              				</div>
              			</div>
              		</div>
              	</div>
              	<div class="slider__pagination-wrapper" data-js-item="slider-pagination">
              		<ol class="slider__pagination-list" data-js-item="slider-pagination-list">
              		</ol>
              	</div>
              </div>