360 lines
8.8 KiB
JavaScript
360 lines
8.8 KiB
JavaScript
(function($, anim) {
|
|
'use strict';
|
|
|
|
let _defaults = {
|
|
indicators: true,
|
|
height: 400,
|
|
duration: 500,
|
|
interval: 6000
|
|
};
|
|
|
|
/**
|
|
* @class
|
|
*
|
|
*/
|
|
class Slider extends Component {
|
|
/**
|
|
* Construct Slider instance and set up overlay
|
|
* @constructor
|
|
* @param {Element} el
|
|
* @param {Object} options
|
|
*/
|
|
constructor(el, options) {
|
|
super(Slider, el, options);
|
|
|
|
this.el.M_Slider = this;
|
|
|
|
/**
|
|
* Options for the modal
|
|
* @member Slider#options
|
|
* @prop {Boolean} [indicators=true] - Show indicators
|
|
* @prop {Number} [height=400] - height of slider
|
|
* @prop {Number} [duration=500] - Length in ms of slide transition
|
|
* @prop {Number} [interval=6000] - Length in ms of slide interval
|
|
*/
|
|
this.options = $.extend({}, Slider.defaults, options);
|
|
|
|
// setup
|
|
this.$slider = this.$el.find('.slides');
|
|
this.$slides = this.$slider.children('li');
|
|
this.activeIndex = this.$slides
|
|
.filter(function(item) {
|
|
return $(item).hasClass('active');
|
|
})
|
|
.first()
|
|
.index();
|
|
if (this.activeIndex != -1) {
|
|
this.$active = this.$slides.eq(this.activeIndex);
|
|
}
|
|
|
|
this._setSliderHeight();
|
|
|
|
// Set initial positions of captions
|
|
this.$slides.find('.caption').each((el) => {
|
|
this._animateCaptionIn(el, 0);
|
|
});
|
|
|
|
// Move img src into background-image
|
|
this.$slides.find('img').each((el) => {
|
|
let placeholderBase64 =
|
|
'data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
|
|
if ($(el).attr('src') !== placeholderBase64) {
|
|
$(el).css('background-image', 'url("' + $(el).attr('src') + '")');
|
|
$(el).attr('src', placeholderBase64);
|
|
}
|
|
});
|
|
|
|
this._setupIndicators();
|
|
|
|
// Show active slide
|
|
if (this.$active) {
|
|
this.$active.css('display', 'block');
|
|
} else {
|
|
this.$slides.first().addClass('active');
|
|
anim({
|
|
targets: this.$slides.first()[0],
|
|
opacity: 1,
|
|
duration: this.options.duration,
|
|
easing: 'easeOutQuad'
|
|
});
|
|
|
|
this.activeIndex = 0;
|
|
this.$active = this.$slides.eq(this.activeIndex);
|
|
|
|
// Update indicators
|
|
if (this.options.indicators) {
|
|
this.$indicators.eq(this.activeIndex).addClass('active');
|
|
}
|
|
}
|
|
|
|
// Adjust height to current slide
|
|
this.$active.find('img').each((el) => {
|
|
anim({
|
|
targets: this.$active.find('.caption')[0],
|
|
opacity: 1,
|
|
translateX: 0,
|
|
translateY: 0,
|
|
duration: this.options.duration,
|
|
easing: 'easeOutQuad'
|
|
});
|
|
});
|
|
|
|
this._setupEventHandlers();
|
|
|
|
// auto scroll
|
|
this.start();
|
|
}
|
|
|
|
static get defaults() {
|
|
return _defaults;
|
|
}
|
|
|
|
static init(els, options) {
|
|
return super.init(this, els, options);
|
|
}
|
|
|
|
/**
|
|
* Get Instance
|
|
*/
|
|
static getInstance(el) {
|
|
let domElem = !!el.jquery ? el[0] : el;
|
|
return domElem.M_Slider;
|
|
}
|
|
|
|
/**
|
|
* Teardown component
|
|
*/
|
|
destroy() {
|
|
this.pause();
|
|
this._removeIndicators();
|
|
this._removeEventHandlers();
|
|
this.el.M_Slider = undefined;
|
|
}
|
|
|
|
/**
|
|
* Setup Event Handlers
|
|
*/
|
|
_setupEventHandlers() {
|
|
this._handleIntervalBound = this._handleInterval.bind(this);
|
|
this._handleIndicatorClickBound = this._handleIndicatorClick.bind(this);
|
|
|
|
if (this.options.indicators) {
|
|
this.$indicators.each((el) => {
|
|
el.addEventListener('click', this._handleIndicatorClickBound);
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove Event Handlers
|
|
*/
|
|
_removeEventHandlers() {
|
|
if (this.options.indicators) {
|
|
this.$indicators.each((el) => {
|
|
el.removeEventListener('click', this._handleIndicatorClickBound);
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle indicator click
|
|
* @param {Event} e
|
|
*/
|
|
_handleIndicatorClick(e) {
|
|
let currIndex = $(e.target).index();
|
|
this.set(currIndex);
|
|
}
|
|
|
|
/**
|
|
* Handle Interval
|
|
*/
|
|
_handleInterval() {
|
|
let newActiveIndex = this.$slider.find('.active').index();
|
|
if (this.$slides.length === newActiveIndex + 1) newActiveIndex = 0;
|
|
// loop to start
|
|
else newActiveIndex += 1;
|
|
|
|
this.set(newActiveIndex);
|
|
}
|
|
|
|
/**
|
|
* Animate in caption
|
|
* @param {Element} caption
|
|
* @param {Number} duration
|
|
*/
|
|
_animateCaptionIn(caption, duration) {
|
|
let animOptions = {
|
|
targets: caption,
|
|
opacity: 0,
|
|
duration: duration,
|
|
easing: 'easeOutQuad'
|
|
};
|
|
|
|
if ($(caption).hasClass('center-align')) {
|
|
animOptions.translateY = -100;
|
|
} else if ($(caption).hasClass('right-align')) {
|
|
animOptions.translateX = 100;
|
|
} else if ($(caption).hasClass('left-align')) {
|
|
animOptions.translateX = -100;
|
|
}
|
|
|
|
anim(animOptions);
|
|
}
|
|
|
|
/**
|
|
* Set height of slider
|
|
*/
|
|
_setSliderHeight() {
|
|
// If fullscreen, do nothing
|
|
if (!this.$el.hasClass('fullscreen')) {
|
|
if (this.options.indicators) {
|
|
// Add height if indicators are present
|
|
this.$el.css('height', this.options.height + 40 + 'px');
|
|
} else {
|
|
this.$el.css('height', this.options.height + 'px');
|
|
}
|
|
this.$slider.css('height', this.options.height + 'px');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Setup indicators
|
|
*/
|
|
_setupIndicators() {
|
|
if (this.options.indicators) {
|
|
this.$indicators = $('<ul class="indicators"></ul>');
|
|
this.$slides.each((el, index) => {
|
|
let $indicator = $('<li class="indicator-item"></li>');
|
|
this.$indicators.append($indicator[0]);
|
|
});
|
|
this.$el.append(this.$indicators[0]);
|
|
this.$indicators = this.$indicators.children('li.indicator-item');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove indicators
|
|
*/
|
|
_removeIndicators() {
|
|
this.$el.find('ul.indicators').remove();
|
|
}
|
|
|
|
/**
|
|
* Cycle to nth item
|
|
* @param {Number} index
|
|
*/
|
|
set(index) {
|
|
// Wrap around indices.
|
|
if (index >= this.$slides.length) index = 0;
|
|
else if (index < 0) index = this.$slides.length - 1;
|
|
|
|
// Only do if index changes
|
|
if (this.activeIndex != index) {
|
|
this.$active = this.$slides.eq(this.activeIndex);
|
|
let $caption = this.$active.find('.caption');
|
|
this.$active.removeClass('active');
|
|
|
|
anim({
|
|
targets: this.$active[0],
|
|
opacity: 0,
|
|
duration: this.options.duration,
|
|
easing: 'easeOutQuad',
|
|
complete: () => {
|
|
this.$slides.not('.active').each((el) => {
|
|
anim({
|
|
targets: el,
|
|
opacity: 0,
|
|
translateX: 0,
|
|
translateY: 0,
|
|
duration: 0,
|
|
easing: 'easeOutQuad'
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
this._animateCaptionIn($caption[0], this.options.duration);
|
|
|
|
// Update indicators
|
|
if (this.options.indicators) {
|
|
this.$indicators.eq(this.activeIndex).removeClass('active');
|
|
this.$indicators.eq(index).addClass('active');
|
|
}
|
|
|
|
anim({
|
|
targets: this.$slides.eq(index)[0],
|
|
opacity: 1,
|
|
duration: this.options.duration,
|
|
easing: 'easeOutQuad'
|
|
});
|
|
|
|
anim({
|
|
targets: this.$slides.eq(index).find('.caption')[0],
|
|
opacity: 1,
|
|
translateX: 0,
|
|
translateY: 0,
|
|
duration: this.options.duration,
|
|
delay: this.options.duration,
|
|
easing: 'easeOutQuad'
|
|
});
|
|
|
|
this.$slides.eq(index).addClass('active');
|
|
this.activeIndex = index;
|
|
|
|
// Reset interval
|
|
this.start();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pause slider interval
|
|
*/
|
|
pause() {
|
|
clearInterval(this.interval);
|
|
}
|
|
|
|
/**
|
|
* Start slider interval
|
|
*/
|
|
start() {
|
|
clearInterval(this.interval);
|
|
this.interval = setInterval(
|
|
this._handleIntervalBound,
|
|
this.options.duration + this.options.interval
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Move to next slide
|
|
*/
|
|
next() {
|
|
let newIndex = this.activeIndex + 1;
|
|
|
|
// Wrap around indices.
|
|
if (newIndex >= this.$slides.length) newIndex = 0;
|
|
else if (newIndex < 0) newIndex = this.$slides.length - 1;
|
|
|
|
this.set(newIndex);
|
|
}
|
|
|
|
/**
|
|
* Move to previous slide
|
|
*/
|
|
prev() {
|
|
let newIndex = this.activeIndex - 1;
|
|
|
|
// Wrap around indices.
|
|
if (newIndex >= this.$slides.length) newIndex = 0;
|
|
else if (newIndex < 0) newIndex = this.$slides.length - 1;
|
|
|
|
this.set(newIndex);
|
|
}
|
|
}
|
|
|
|
M.Slider = Slider;
|
|
|
|
if (M.jQueryLoaded) {
|
|
M.initializeJqueryWrapper(Slider, 'slider', 'M_Slider');
|
|
}
|
|
})(cash, M.anime);
|