/** * Flickity fade v1.0.0 * Fade between Flickity slides */ /* jshint browser: true, undef: true, unused: true */ ( function( window, factory ) { // universal module definition /*globals define, module, require */ if ( typeof define == 'function' && define.amd ) { // AMD define( [ 'flickity/js/index', 'fizzy-ui-utils/utils', ], factory ); } else if ( typeof module == 'object' && module.exports ) { // CommonJS module.exports = factory( require('flickity'), require('fizzy-ui-utils') ); } else { // browser global factory( window.Flickity, window.fizzyUIUtils ); } }( this, function factory( Flickity, utils ) { // ---- Slide ---- // var Slide = Flickity.Slide; var slideUpdateTarget = Slide.prototype.updateTarget; Slide.prototype.updateTarget = function() { slideUpdateTarget.apply( this, arguments ); if ( !this.parent.options.fade ) { return; } // position cells at selected target var slideTargetX = this.target - this.x; var firstCellX = this.cells[0].x; this.cells.forEach( function( cell ) { var targetX = cell.x - firstCellX - slideTargetX; cell.renderPosition( targetX ); }); }; Slide.prototype.setOpacity = function( alpha ) { this.cells.forEach( function( cell ) { cell.element.style.opacity = alpha; }); }; // ---- Flickity ---- // var proto = Flickity.prototype; Flickity.createMethods.push('_createFade'); proto._createFade = function() { this.fadeIndex = this.selectedIndex; this.prevSelectedIndex = this.selectedIndex; this.on( 'select', this.onSelectFade ); this.on( 'dragEnd', this.onDragEndFade ); this.on( 'settle', this.onSettleFade ); this.on( 'activate', this.onActivateFade ); this.on( 'deactivate', this.onDeactivateFade ); }; var updateSlides = proto.updateSlides; proto.updateSlides = function() { updateSlides.apply( this, arguments ); if ( !this.options.fade ) { return; } // set initial opacity this.slides.forEach( function( slide, i ) { var alpha = i == this.selectedIndex ? 1 : 0; slide.setOpacity( alpha ); }, this ); }; /* ---- events ---- */ proto.onSelectFade = function() { // in case of resize, keep fadeIndex within current count this.fadeIndex = Math.min( this.prevSelectedIndex, this.slides.length - 1 ); this.prevSelectedIndex = this.selectedIndex; }; proto.onSettleFade = function() { delete this.didDragEnd; if ( !this.options.fade ) { return; } // set full and 0 opacity on selected & faded slides this.selectedSlide.setOpacity( 1 ); var fadedSlide = this.slides[ this.fadeIndex ]; if ( fadedSlide && this.fadeIndex != this.selectedIndex ) { this.slides[ this.fadeIndex ].setOpacity( 0 ); } }; proto.onDragEndFade = function() { // set flag this.didDragEnd = true; }; proto.onActivateFade = function() { if ( this.options.fade ) { this.element.classList.add('is-fade'); } }; proto.onDeactivateFade = function() { if ( !this.options.fade ) { return; } this.element.classList.remove('is-fade'); // reset opacity this.slides.forEach( function( slide ) { slide.setOpacity(''); }); }; /* ---- position & fading ---- */ var positionSlider = proto.positionSlider; proto.positionSlider = function() { if ( !this.options.fade ) { positionSlider.apply( this, arguments ); return; } this.fadeSlides(); this.dispatchScrollEvent(); }; var positionSliderAtSelected = proto.positionSliderAtSelected; proto.positionSliderAtSelected = function() { if ( this.options.fade ) { // position fade slider at origin this.setTranslateX( 0 ); } positionSliderAtSelected.apply( this, arguments ); }; proto.fadeSlides = function() { if ( this.slides.length < 2 ) { return; } // get slides to fade-in & fade-out var indexes = this.getFadeIndexes(); var fadeSlideA = this.slides[ indexes.a ]; var fadeSlideB = this.slides[ indexes.b ]; var distance = this.wrapDifference( fadeSlideA.target, fadeSlideB.target ); var progress = this.wrapDifference( fadeSlideA.target, -this.x ); progress = progress / distance; fadeSlideA.setOpacity( 1 - progress ); fadeSlideB.setOpacity( progress ); // hide previous slide var fadeHideIndex = indexes.a; if ( this.isDragging ) { fadeHideIndex = progress > 0.5 ? indexes.a : indexes.b; } var isNewHideIndex = this.fadeHideIndex != undefined && this.fadeHideIndex != fadeHideIndex && this.fadeHideIndex != indexes.a && this.fadeHideIndex != indexes.b; if ( isNewHideIndex ) { // new fadeHideSlide set, hide previous this.slides[ this.fadeHideIndex ].setOpacity( 0 ); } this.fadeHideIndex = fadeHideIndex; }; proto.getFadeIndexes = function() { if ( !this.isDragging && !this.didDragEnd ) { return { a: this.fadeIndex, b: this.selectedIndex, }; } if ( this.options.wrapAround ) { return this.getFadeDragWrapIndexes(); } else { return this.getFadeDragLimitIndexes(); } }; proto.getFadeDragWrapIndexes = function() { var distances = this.slides.map( function( slide, i ) { return this.getSlideDistance( -this.x, i ); }, this ); var absDistances = distances.map( function( distance ) { return Math.abs( distance ); }); var minDistance = Math.min.apply( Math, absDistances ); var closestIndex = absDistances.indexOf( minDistance ); var distance = distances[ closestIndex ]; var len = this.slides.length; var delta = distance >= 0 ? 1 : -1; return { a: closestIndex, b: utils.modulo( closestIndex + delta, len ), }; }; proto.getFadeDragLimitIndexes = function() { // calculate closest previous slide var dragIndex = 0; for ( var i=0; i < this.slides.length - 1; i++ ) { var slide = this.slides[i]; if ( -this.x < slide.target ) { break; } dragIndex = i; } return { a: dragIndex, b: dragIndex + 1, }; }; proto.wrapDifference = function( a, b ) { var diff = b - a; if ( !this.options.wrapAround ) { return diff; } var diffPlus = diff + this.slideableWidth; var diffMinus = diff - this.slideableWidth; if ( Math.abs( diffPlus ) < Math.abs( diff ) ) { diff = diffPlus; } if ( Math.abs( diffMinus ) < Math.abs( diff ) ) { diff = diffMinus; } return diff; }; // ---- wrapAround ---- // var _getWrapShiftCells = proto._getWrapShiftCells; proto._getWrapShiftCells = function() { if ( !this.options.fade ) { _getWrapShiftCells.apply( this, arguments ); } }; var shiftWrapCells = proto.shiftWrapCells; proto.shiftWrapCells = function() { if ( !this.options.fade ) { shiftWrapCells.apply( this, arguments ); } }; return Flickity; }));