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