(function( window, $, undefined ) { var $event = $.event, resizeTimeout; $event.special.smartresize = { setup: function() { $(this).bind( "resize", $event.special.smartresize.handler ); }, teardown: function() { $(this).unbind( "resize", $event.special.smartresize.handler ); }, handler: function( event, execAsap ) { // Save the context var context = this, args = arguments; // set correct event type event.type = "smartresize"; if ( resizeTimeout ) { clearTimeout( resizeTimeout ); } resizeTimeout = setTimeout(function() { jQuery.event.handle.apply( context, args ); }, execAsap === "execAsap"? 0 : 100 ); } }; $.fn.smartresize = function( fn ) { return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] ); }; $.Slideshow = function( options, element ) { this.$el = $( element ); /***** images ****/ // list of image items this.$list = this.$el.find('ul.ei-slider-large'); // image items this.$imgItems = this.$list.children('li'); // total number of items this.itemsCount = this.$imgItems.length; // images this.$images = this.$imgItems.find('img:first'); /***** thumbs ****/ // thumbs wrapper this.$sliderthumbs = this.$el.find('ul.ei-slider-thumbs').hide(); // slider elements this.$sliderElems = this.$sliderthumbs.children('li'); // sliding div this.$sliderElem = this.$sliderthumbs.children('li.ei-slider-element'); // thumbs this.$thumbs = this.$sliderElems.not('.ei-slider-element'); // initialize slideshow this._init( options ); }; $.Slideshow.defaults = { // animation types: // "sides" : new slides will slide in from left / right // "center": new slides will appear in the center animation : 'sides', // sides || center // if true the slider will automatically slide, and it will only stop if the user clicks on a thumb autoplay : false, // interval for the slideshow slideshow_interval : 3000, // speed for the sliding animation speed : 800, // easing for the sliding animation easing : '', // percentage of speed for the titles animation. Speed will be speed * titlesFactor titlesFactor : 0.60, // titles animation speed titlespeed : 800, // titles animation easing titleeasing : '', // maximum width for the thumbs in pixels thumbMaxWidth : 150 }; $.Slideshow.prototype = { _init : function( options ) { this.options = $.extend( true, {}, $.Slideshow.defaults, options ); // set the opacity of the title elements and the image items this.$imgItems.css( 'opacity', 0 ); this.$imgItems.find('div.ei-title > *').css( 'opacity', 0 ); // index of current visible slider this.current = 0; var _self = this; // preload images // add loading status this.$loading = $('
Loading
').prependTo( _self.$el ); $.when( this._preloadImages() ).done( function() { // hide loading status _self.$loading.hide(); // calculate size and position for each image _self._setImagesSize(); // configure thumbs container _self._initThumbs(); // show first _self.$imgItems.eq( _self.current ).css({ 'opacity' : 1, 'z-index' : 10 }).show().find('div.ei-title > *').css( 'opacity', 1 ); // if autoplay is true if( _self.options.autoplay ) { _self._startSlideshow(); } // initialize the events _self._initEvents(); }); }, _preloadImages : function() { // preloads all the large images var _self = this, loaded = 0; return $.Deferred( function(dfd) { _self.$images.each( function( i ) { $('').load( function() { if( ++loaded === _self.itemsCount ) { dfd.resolve(); } }).attr( 'src', $(this).attr('src') ); }); } ).promise(); }, _setImagesSize : function() { // save ei-slider's width this.elWidth = this.$el.width(); var _self = this; this.$images.each( function( i ) { var $img = $(this); imgDim = _self._getImageDim( $img.attr('src') ); $img.css({ width : imgDim.width, height : imgDim.height, marginLeft : imgDim.left, marginTop : imgDim.top }); }); }, _getImageDim : function( src ) { var $img = new Image(); $img.src = src; var c_w = this.elWidth, c_h = this.$el.height(), r_w = c_h / c_w, i_w = $img.width, i_h = $img.height, r_i = i_h / i_w, new_w, new_h, new_left, new_top; if( r_w > r_i ) { new_h = c_h; new_w = c_h / r_i; } else { new_h = c_w * r_i; new_w = c_w; } return { width : new_w, height : new_h, left : ( c_w - new_w ) / 2, top : ( c_h - new_h ) / 2 }; }, _initThumbs : function() { // set the max-width of the slider elements to the one set in the plugin's options // also, the width of each slider element will be 100% / total number of elements this.$sliderElems.css({ 'max-width' : this.options.thumbMaxWidth + 'px', 'width' : 100 / this.itemsCount + '%' }); // set the max-width of the slider and show it this.$sliderthumbs.css( 'max-width', this.options.thumbMaxWidth * this.itemsCount + 'px' ).show(); }, _startSlideshow : function() { var _self = this; this.slideshow = setTimeout( function() { var pos; ( _self.current === _self.itemsCount - 1 ) ? pos = 0 : pos = _self.current + 1; _self._slideTo( pos ); if( _self.options.autoplay ) { _self._startSlideshow(); } }, this.options.slideshow_interval); }, // shows the clicked thumb's slide _slideTo : function( pos ) { // return if clicking the same element or if currently animating if( pos === this.current || this.isAnimating ) return false; this.isAnimating = true; var $currentSlide = this.$imgItems.eq( this.current ), $nextSlide = this.$imgItems.eq( pos ), _self = this, preCSS = {zIndex : 10}, animCSS = {opacity : 1}; // new slide will slide in from left or right side if( this.options.animation === 'sides' ) { preCSS.left = ( pos > this.current ) ? -1 * this.elWidth : this.elWidth; animCSS.left = 0; } // titles animation $nextSlide.find('div.ei-title > h2') .css( 'margin-right', 50 + 'px' ) .stop() .delay( this.options.speed * this.options.titlesFactor ) .animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing ) .end() .find('div.ei-title > p') .css( 'margin-right', -50 + 'px' ) .stop() .delay( this.options.speed * this.options.titlesFactor ) .animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing ) $.when( // fade out current titles $currentSlide.css( 'z-index' , 1 ).find('div.ei-title > *').stop().fadeOut( this.options.speed / 2, function() { // reset style $(this).show().css( 'opacity', 0 ); }), // animate next slide in $nextSlide.css( preCSS ).stop().animate( animCSS, this.options.speed, this.options.easing ), // "sliding div" moves to new position this.$sliderElem.stop().animate({ left : this.$thumbs.eq( pos ).position().left }, this.options.speed ) ).done( function() { // reset values $currentSlide.css( 'opacity' , 0 ).find('div.ei-title > *').css( 'opacity', 0 ); _self.current = pos; _self.isAnimating = false; }); }, _initEvents : function() { var _self = this; // window resize $(window).on( 'smartresize.eislideshow', function( event ) { // resize the images _self._setImagesSize(); // reset position of thumbs sliding div _self.$sliderElem.css( 'left', _self.$thumbs.eq( _self.current ).position().left ); }); // click the thumbs this.$thumbs.on( 'click.eislideshow', function( event ) { if( _self.options.autoplay ) { clearTimeout( _self.slideshow ); _self.options.autoplay = false; } var $thumb = $(this), idx = $thumb.index() - 1; // exclude sliding div _self._slideTo( idx ); return false; }); } }; var logError = function( message ) { if ( this.console ) { console.error( message ); } }; $.fn.eislideshow = function( options ) { if ( typeof options === 'string' ) { var args = Array.prototype.slice.call( arguments, 1 ); this.each(function() { var instance = $.data( this, 'eislideshow' ); if ( !instance ) { logError( "cannot call methods on eislideshow prior to initialization; " + "attempted to call method '" + options + "'" ); return; } if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) { logError( "no such method '" + options + "' for eislideshow instance" ); return; } instance[ options ].apply( instance, args ); }); } else { this.each(function() { var instance = $.data( this, 'eislideshow' ); if ( !instance ) { $.data( this, 'eislideshow', new $.Slideshow( options, this ) ); } }); } return this; }; })( window, jQuery );