/*
* We trigger the factory() function is different
* ways to support modular JavaScript libraries.
*/
;(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports !== 'undefined') {
module.exports = factory(require('jquery'));
} else {
factory(jQuery);
}
})(function ($) {
let MioCarousel = (function (element, settings) {
function _MioCarousel(element, settings) {
let duration = 3000;
let speed = 500;
let autoplay = 1;
let indicators = 1;
let animation = 'fade';
let height = 0;
let showDelayed = 0;
if ($(element).is('[data-duration]')) duration = $(element).attr("data-duration");
if ($(element).is('[data-speed]')) speed = parseInt($(element).attr("data-speed"));
if ($(element).is('[data-autoplay]')) autoplay = parseInt($(element).attr("data-autoplay"));
if ($(element).is('[data-indicators]')) indicators = parseInt($(element).attr("data-indicators"));
if ($(element).is('[data-animation]')) animation = $(element).attr("data-animation");
if ($(element).is('[data-height]')) height = $(element).attr("data-height");
this.defaults = {
slideDuration: duration,
speed: speed,
indicators: indicators,
animation: animation,
arrowRight: '.mc_arrow_container-right',
arrowLeft: '.mc_arrow_container-left',
autoplay: autoplay,
height: height,
};
this.settings = $.extend({}, this, this.defaults, settings);
// This object holds values that will change as the plugin operates
this.initials = {
currSlide: 0,
nextSlide: 0,
visibleItems: 0,
correction: 0,
slideWidth: '100%',
totalSlides: false,
isReordered: false,
};
// Attaches the properties of this.initials as direct properties of MioCarousel
$.extend(this, this.initials);
this.$el = $(element);
// Ensure that the value of 'this' always references MioCarousel
this.changeSlide = $.proxy(this.changeSlide, this);
let obj = this;
let $delayContainer = this.$el.closest('.element_container_delay');
if($delayContainer.length) {
showDelayed = parseFloat($delayContainer.attr('data-delay'));
}
if(showDelayed > 0) {
setTimeout(function () {
obj.init();
}, (showDelayed * 1000) + 100);
} else {
this.init();
}
let res;
let lastWindowWidth = $(window).width();
$(window).resize(function () {
let currentWindowWidth = $(window).width();
if (currentWindowWidth !== lastWindowWidth) {
clearTimeout(res);
res = setTimeout(function () {
obj.onResize();
}, 200);
lastWindowWidth = currentWindowWidth;
}
});
}
return _MioCarousel;
})();
/**
* Called once per instance
* @params void
* @returns void
*
*/
MioCarousel.prototype.init = function (setInterval = true) {
this.$el.find('.mw_fake_slide').remove();
this.$slides = this.$el.find('.slide');
// set speed animation
this.$el.get(0).style.setProperty('--animation-speed', this.settings.speed/1000 + 's');
this.currSlide = 0;
if(this.settings.animation !== 'fade') {
this.processSlides();
}
this.totalSlides = this.$slides.length;
if (this.settings.animation === 'slide') {
this.totalSlides = Math.ceil(this.totalSlides / this.visibleItems);
} else if (this.settings.animation === 'slideone') {
this.$el.find('.miocarousel_slides').get(0).style.setProperty('--slide-width', this.slideWidth);
}
if(this.settings.animation === 'slide' && this.totalSlides * this.visibleItems > this.$slides.length) {
let count = this.totalSlides * this.visibleItems - this.$slides.length;
for (let i = 0; i < count; i++) {
this.$el.find('.miocarousel_slides').append('
');
}
this.$slides = this.$el.find('.slide');
}
this.build();
if (this.totalSlides > 1) {
this.events();
if(setInterval) {
this.initTimer();
}
}
};
/**
* Creates a list of indicators based on the amount of slides
* @params void
* @returns void
*
*/
MioCarousel.prototype.build = function () {
this.$el.find('.indicators').remove();
var $indicators = this.$el.append('').find('.indicators');
for (var i = 0; i < this.totalSlides; i++) $indicators.append('');
this.$el.find('.indicators li').eq(0).addClass('active');
};
/**
* Activates the first slide
* Activates the first indicator
* @params void
* @returns void
*
*
MioCarousel.prototype.activate = function () {
this.$el.find('.slide').removeClass('active');
this.$el.find('.indicators li').removeClass('active');
this.$currSlide = this.$el.find('.slide').eq(0);
this.$el.find('.slide').eq(0).addClass('active');
};*/
MioCarousel.prototype.onResize = function () {
this.clearTimer();
this.$el.removeClass('transition');
this.setSlide(0);
this.visibleItems = 0;
this.init(true);
this.reorder(0);
this.setSlide(0);
};
MioCarousel.prototype.processSlides = function () {
let visibleItems = 0;
let order = 0;
const rectContainer = this.$el.find('.miocarousel-inner').get(0).getBoundingClientRect();
const tolerance = (rectContainer.right - rectContainer.left) * 0.1;
// find visible items
this.$slides.removeClass('active');
this.$slides.each(function() {
const rectSlide = $(this).get(0).getBoundingClientRect();
if(rectSlide.left >= (rectContainer.left - tolerance) && rectSlide.right <= (rectContainer.right + tolerance)) {
$(this).addClass('active');
visibleItems++;
}
$(this).attr('data-order', order);
order++;
});
// number of visible items
if (this.visibleItems === 0) {
this.visibleItems = visibleItems;
}
if(this.$slides.length > 1) {
let first = this.$slides.get(0).getBoundingClientRect();
let second = this.$slides.get(1).getBoundingClientRect();
this.slideWidth = (second.left - first.left) + 'px';
}
};
/**
* Associate event handlers to events
* For arrow events, we send the placement of the next slide to the handler
* @params void
* @returns void
*
*/
MioCarousel.prototype.events = function () {
this.unbindEvents();
this.$el
.on('click', this.settings.arrowRight, {direction: 'right'}, this.changeSlide)
.on('click', this.settings.arrowLeft, {direction: 'left'}, this.changeSlide)
.on('click', '.indicators li', this.changeSlide);
};
MioCarousel.prototype.unbindEvents = function () {
this.$el.off('click', this.settings.arrowRight);
this.$el.off('click', this.settings.arrowLeft);
this.$el.off('click', '.indicators li');
}
/**
* TIMER
* Resets the timer
* @params void
* @returns void
*
*/
MioCarousel.prototype.clearTimer = function () {
if (this.timer) clearInterval(this.timer);
};
/**
* TIMER
* Initialise the timer
* @params void
* @returns void
*
*/
MioCarousel.prototype.initTimer = function () {
if (this.settings.autoplay) this.timer = setInterval(this.changeSlide, this.settings.slideDuration);
};
/**
* MAIN LOGIC HANDLER
* Triggers a set of subfunctions to carry out the animation
* @params object event
* @returns void
*
*/
MioCarousel.prototype.changeSlide = function (e) {
//Ensure that animations are triggered one at a time
if (this.throttle) return;
this.throttle = true;
//Stop the timer as the animation is getting carried out
this.clearTimer();
// Returns the animation direction (left or right)
let direction = this._direction(e);
// Selects the next slide
let animate = this._next(e, direction);
if (!animate) return;
this.reorderSlides(direction);
this._Animation(this);
};
MioCarousel.prototype.reorderSlides = function (direction) {
if (this.settings.animation === 'fade') {
return;
}
let correction = 0;
/*
console.log('next:' + this.nextSlide);
console.log('slide:' + this.currSlide);
console.log('cor:' + this.correction);
console.log(direction);
console.log('-------');
*/
if (this.nextSlide < 0) {
correction = (this.nextSlide + this.correction) * this.itemsPerSlide();
this.reorder(correction);
this.nextSlide = 0;
this.setSlide(1);
} else if (this.nextSlide > (this.totalSlides - this.visibleSlides())) {
correction = (this.nextSlide + this.correction - (this.totalSlides - this.visibleSlides())) * this.itemsPerSlide();
this.reorder(correction);
this.nextSlide = this.currSlide;
this.setSlide(this.currSlide - 1);
}
/*
console.log('next:' + this.nextSlide);
console.log('slide:' + this.currSlide);
console.log('cor:' + this.correction);
console.log('-------------------------');
*/
};
MioCarousel.prototype.reorder = function (correction) {
if (correction < 0) {
this.$slides.slice(correction).css('order', -1);
} else if (correction > 0) {
this.$slides.slice(0,correction).css('order', 99999);
} else {
this.$slides.css('order', 1);
}
this.correction = correction;
};
MioCarousel.prototype.itemsPerSlide = function () {
if (this.settings.animation === 'slide') {
return this.visibleItems;
}
return 1;
};
MioCarousel.prototype.visibleSlides = function () {
if (this.settings.animation === 'slideone') {
return this.visibleItems;
}
return 1;
};
MioCarousel.prototype.isEndSlide = function () {
if(this.isBeginning() || this.isEnd() ) {
return true;
}
return false;
};
MioCarousel.prototype.isEnd = function () {
if(this.correction === (this.visibleSlides() * this.itemsPerSlide()) ) {
return true;
}
return false;
};
MioCarousel.prototype.isBeginning = function () {
if(this.correction === -(this.visibleSlides() * this.itemsPerSlide())) {
return true;
}
return false;
};
/**
* Returns the animation direction, right or left
* @params object event
* @returns strong animation direction
*
*/
MioCarousel.prototype._direction = function (e) {
let direction;
// Default to forward movement
if (typeof e !== 'undefined') {
direction = (typeof e.data === 'undefined' ? 'right' : e.data.direction);
} else {
direction = 'right';
}
return direction;
};
/**
* Updates our plugin with the next slide number
* @params object event
* @params string animation direction
* @returns boolean continue to animate?
*
*/
MioCarousel.prototype._next = function (e, direction) {
// to default order
if (this.isEndSlide() && this.settings.animation !== 'fade') {
let jumpToSlide;
if (this.isBeginning()) {
jumpToSlide = this.totalSlides - this.visibleSlides();
} else if(this.isEnd()) {
jumpToSlide = 0;
}
this.reorder(0);
this.setSlide(jumpToSlide);
}
// If the event was triggered by a slide indicator, we store the data-index value of that indicator
let index = (typeof e !== 'undefined' ? $(e.currentTarget).data('index') : undefined);
//Logic for determining the next slide
switch (true) {
//If the event was triggered by an indicator, we set the next slide based on index
case(typeof index !== 'undefined'):
/*
if (this.nextSlide == index + 1) {
this.initTimer();
return false;
}*/
if(this.currSlide === 0 && index >= this.totalSlides - 1) {
this.nextSlide = -1
} else if(this.currSlide - this.correction === (this.totalSlides - 1) && index === 0) {
this.nextSlide = this.currSlide + 1;
} else {
this.nextSlide = index - this.correction;
}
break;
case(direction == 'right'):
this.nextSlide = this.currSlide + 1;
break;
case(direction == 'left'):
this.nextSlide = this.currSlide - 1;
break;
}
return true;
};
/**
* Executes the animation
* @params object Jquery object the next slide to slide into view
* @params string animation direction
* @returns void
*
*/
MioCarousel.prototype._Animation = function (obj) {
setTimeout(function () {
obj.$el.addClass('transition');
obj.setSlide(this.nextSlide);
obj._updateIndicators();
setTimeout(obj.afterAnimation, obj.settings.speed, this);
}.bind(this), 10);
};
MioCarousel.prototype.setSlide = function (nextSlide) {
if (this.settings.animation === 'fade') {
if(nextSlide > (this.totalSlides - 1)) {
nextSlide = 0;
} else if(nextSlide < 0) {
nextSlide = (this.totalSlides - 1);
}
let $nextSlide = this.$el.find('.slide').eq(nextSlide);
let $currSlide = this.$el.find('.slide').eq(this.currSlide);
$currSlide.removeClass('active');
$nextSlide.addClass('active');
} else {
this.$el.find('.miocarousel_slides').get(0).style.setProperty('--current-slide', nextSlide);
}
this.currSlide = nextSlide;
};
MioCarousel.prototype.afterAnimation = function (obj) {
obj.initTimer();
obj.$el.removeClass('transition');
if(obj.settings.animation !== 'fade') {
obj.processSlides();
}
obj.throttle = false;
};
/**
* Ensures the slide indicators are pointing to the currently active slide
* @params void
* @returns void
*
*/
MioCarousel.prototype._updateIndicators = function () {
let id = this.currSlide + (this.correction / this.itemsPerSlide());
if (id < 0) {
id = this.totalSlides + (this.correction / this.itemsPerSlide());
} else if (id >= this.totalSlides) {
id = this.correction - (this.visibleSlides() * this.itemsPerSlide());
}
this.$el.find('.indicators li').removeClass('active').eq(id).addClass('active');
};
/**
* Initialize the plugin once for each DOM object passed to jQuery
* @params object options object
* @returns void
*
*/
$.fn.MioCarousel = function (options) {
return this.each(function (index, el) {
el.MioCarousel = new MioCarousel(el, options);
});
};
});
jQuery(function ($) {
$('.miocarousel:not(.ve_popup_container .miocarousel)').MioCarousel({});
});