Each variation will be presented in the following sections.
By providing 'visibleItems' you can define the visible active slides per breakpoint.
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'.
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.
By providing 'sliderOverflow' you can display all other items next to the active slide(s) as well.
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.
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.
Veams >= v5.0.0
- Veams Framework.veams install vc slider
bower install veams-component-slider --save
c-slider.hbs
The partial is a wrapWith
partial.
String
} [default] - Context class of component.String
} - Modifier classes for component.Object
} - JavaScript options which gets stringified.Boolean
} [false] - Delete the class .is-container
from .slider__content
.Boolean
} [false] - Hide the pagination when set to true.c-slider__controls.hbs
Object
} - Contains the controls content. When the object is not defined, the controls will not be printed out.String
} - Define the button text for the previous button.String
} - Define the button text for the next button.c-slider__list.hbs
The partial is a wrapWith
partial.
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.
The module gives you the possibility to override default options:
String
} [‘is-active’] - Class for the active slide.String
} [’[data-js-item=“slider-actions”]’] - Actions wrapper element in the component.Boolean
} [false] - Enable autoplay option of the slider.Number
} [3000] - Autoplay speed in milliseconds.String
} [‘is-cloned’] - For the infinite slider the last and first element get cloned. The cloning class can be overriden.Boolean
} [false] - Disable pagination.Boolean
} [true] - Enable support for swipe gestures on touch devices.Boolean
} [true] - Enable the grouping of pagination items.String
} [‘is-hidden’] - The hidden class used by handling the visibility of the slider.Boolean
} [‘is-closed’] - The slider will be set in infinite mode. Can not be used with multiple active slide items.String
} [’[data-js-item=“slider-item”]’] - Define the slide item element.String
} [’[data-js-item=“slider-next”]’] - Define the next button element.String
} [’[data-js-item=“slider-prev”]’] - Define the prev button element.String
} [’[data-js-item=“slider-pagination”]’] - Define the pagination element in which the pagination items are generated in.String
} [‘slider__pagination-list-item’] - Class for the generated pagination item.String
} [‘slider-pagination-item’] - Data attribute for the generated pagination item.String
} [’[data-js-item=“slider-pagination-list”]’] - Define the pagination list element in which the pagination items are generated in.String
} [’[data-js-item=“slider-ribbon”]’] - Define the slider ribbon which is holding all slides and gets the full width.Boolean
} [true] - When autoplay
is set you can enable/disable pause on hover.Number
} [false] - You can use the option to override the initial slide step which is the number of current visible items.Number
} [0] - Start index for the slider.Number
} [null] - Index of panel to be opened on init (zero based).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.String
} [’[data-js-item=“slider-wrapper”]’] - Define the slider wrapper element.There are multiple global variables which you can change:
10 !default
] - Darken value for hover effects.300px !default
] - Set a fix height when the slider is in unresolved state.600ms !default
] - Slide item animation duration.ease !default
] - Slide item animation ease method.#a5cfd1 !default
] - Background color of control buttons.[#555 !default
] - Background color of pagination items.[$slider-pagination-color !default
] - Active vackground color of pagination items which gets darken by $slider-darken
.15px !default
] - Pagination size (width & height).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"
}
}
}
}
}
{{! 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}}
<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>
<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;
}
/**
* 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;
<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>
<div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{"visibleItems":{"desktop":3,"tablet-large":2,"tablet-small":2,"mobile-large":2,"mobile-medium":1,"mobile-small":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>
<div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{"groupPaginationItems":true,"slideByItemNumber":1,"visibleItems":{"desktop":3,"tablet-large":2,"tablet-small":2,"mobile-large":2,"mobile-medium":1,"mobile-small":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>
<div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{"infinite":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>
<div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{"infinite":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>
<div class="c-slider--default default" data-css="c-slider" data-js-module="slider" data-js-options='{"infinite":true,"autoPlay":true,"autoPlayInterval":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>