(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 = $(''); this.$slides.each((el, index) => { let $indicator = $('
  • '); 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);