infojune/resources/sass/materialize/js/slider.js

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);