/* * zoomSlider - v0.2.3 * CSS3 background zoom slideshow * http://mingthings.com * * Made by Ming Yeung * Under MIT License */ ;(function ( $, window, document, undefined ) { var pluginName = "zoomSlider", defaults = { src: null, speed: 3000, switchSpeed: 800, interval: 5000, autoplay: true, bullets: true, overlay: 'plain' // false, plain, dots }; // The actual plugin constructor function Plugin ( element, options ) { this.element = element; this.$el = $(element); this._defaults = defaults; this._name = pluginName; var elData = this.$el.data(); var elDataObj = {}; for (var key in elData) { if ( elData.hasOwnProperty(key) ) { if ( key.match(/zs[A-Z]/) ) { var keyName = key.substr(2); keyName = keyName.charAt(0).toLowerCase() + keyName.slice(1); elDataObj[keyName] = elData[key] } } } this.settings = $.extend( {}, defaults, elDataObj, options ); if ( this.settings.src == null || this.settings.src.length < 1 ) { console.log('ZoomSlider terminated - invalid input.'); return; } this.init(); } // Avoid Plugin.prototype conflicts $.extend(Plugin.prototype, { init: function () { // Place initialization logic here // You already have access to the DOM element and // the options via the instance, e.g. this.element // and this.settings // you can add more functions like the one below and // call them like so: this.yourOtherFunction(this.element, this.settings). // make sure src is an Array if ($.isArray(this.settings.src) == false) { this.settings.src = [this.settings.src]; } // https://github.com/twitter/bootstrap/issues/2870 this.transEndEventNames = { 'WebkitTransition' : 'webkitTransitionEnd', 'MozTransition' : 'transitionend', 'OTransition' : 'oTransitionEnd', 'msTransition' : 'MSTransitionEnd', 'transition' : 'transitionend' }; this.transEndEventName = this.transEndEventNames[ Modernizr.prefixed( 'transition' ) ]; // suport for css transforms and css transitions this.support = Modernizr.csstransitions && Modernizr.csstransforms; // set inline CSS3 transition properties var transformPrefixed = Modernizr.prefixed('transform'); transformPrefixed = transformPrefixed.replace(/([A-Z])/g, function(transformPrefixed,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); this.transitionProp = { 'transition': transformPrefixed+' '+this.settings.speed+'ms ease-out, opacity '+this.settings.switchSpeed+'ms' }; this.numSlides = this.settings.src.length; // make sure the container is not [position: static] switch(this.$el.css('position')) { case 'relative': case 'absolute': case 'fixed': break; default: this.$el.css('position', 'relative'); break; } // make sure the first image has been loaded. var self = this; var $img = $(''); $img.load( function() { if (self.numSlides == 1) { self.initSingle(); } else { self.initSlideshow(); } }); $img.attr('src', this.settings.src[0]); }, initSlideshow: function () { var self = this; var $slideshow = $('
'), $slidesWrap = $('
'), $bulletsWrap = $('
'); for (i = 0; i < this.numSlides; i++) { var $slide = $('
'); $slide.css({ 'background-image': "url('" + this.settings.src[i] + "')" }).appendTo( $slidesWrap ); var $bullet = $('
') $bullet.appendTo( $bulletsWrap ); if (i == 0) { $slide.addClass('active').css('opacity', 1); $bullet.addClass('active'); } } self._promoteChildren(); $slideshow.append( $slidesWrap ).prependTo( this.$el ); if ( this.settings.bullets == true ) { $slideshow.append( $bulletsWrap ); $slideshow.on('click', '.zs-bullet', function(e){ self.jump( $(this).index() ); }); } this.pos = 0; this.pending = null; this.switching = false; this.$slideshow = $slideshow; this.$slides = $slidesWrap.children( '.zs-slide' ); this.$bullets = $bulletsWrap.children( '.zs-bullet' ); this.$el.addClass('zs-enabled'); if (this.settings.overlay == 'dots') { this.$el.addClass('overlay-dots'); } else if (this.settings.overlay == 'plain') { this.$el.addClass('overlay-plain') } if (this.support) { var $firstSlide = this.$slides.eq(0); $firstSlide.css('opacity', 0).css( this.transitionProp ); setTimeout(function(){ $firstSlide.css( { 'opacity': 1.0, 'transform': 'scale(1.0, 1.0)', 'z-index': 2 } ); }, 50); } if (this.settings.autoplay == true) { this.play(); } }, initSingle: function() { var self = this; var $slideshow = $('
'), $slidesWrap = $('
'), $slide = $('
'); $slide.css({ 'background-image': "url('" + this.settings.src[0] + "')" }).appendTo( $slidesWrap ); $slide.addClass('active').css('opacity', 1); self._promoteChildren(); $slideshow.append( $slidesWrap ).prependTo( this.$el ); this.$el.addClass('zs-enabled'); if (this.settings.overlay == 'dots') { this.$el.addClass('overlay-dots'); } else if (this.settings.overlay == 'plain') { this.$el.addClass('overlay-plain') } if (this.support) { $slide.css('opacity', 0).css( this.transitionProp ); setTimeout(function(){ $slide.css( { 'opacity': 1.0, 'transform': 'scale(1.0, 1.0)', 'z-index': 2 } ); }, 50); } }, _promoteChildren: function() { // make sure every children have high enough z-index this.$el.children().each(function(index){ $this = $(this); if ($this.css('z-index') == 'auto') { $this.css('z-index', 2); } if ($this.css('position') == 'static') { $this.css('position', 'relative'); } }); }, jump: function( pos ) { if ( pos >= this.numSlides ) { console.log('ZoomSlider: jump(pos) aborted. supplied index out of range.'); return; } if ( this.pos == pos ) return; if ( this.switching ) { this.pending = pos; return; } var self = this; var $lastSlide = this.$slides.eq( this.pos ); var $nowSlide = this.$slides.eq( pos ); if ( this.support ) { this.switching = true; $lastSlide.css('z-index', 1); $nowSlide.addClass('active') .css( this.transitionProp ) .css( { 'opacity': 1.0, 'transform': 'scale(1.0, 1.0)', 'z-index': 2 } ) .on( this.transEndEventName, function(e) { if (e.originalEvent.propertyName == 'opacity') { lastSlideBg = $lastSlide.css('background-image'); $lastSlide.removeClass('active') .removeAttr('style') .css('background-image', lastSlideBg); $nowSlide.off( self.transEndEventName ); self.switching = false; if ( self.pending != null ) { setTimeout(function(){ var newPos = self.pending; self.pending = null; self.$bullets.eq(newPos).click(); }, 30) } } }); } else { $lastSlide.removeClass('active'); $nowSlide.addClass('active'); } this.$bullets.eq(this.pos).removeClass('active'); this.$bullets.eq(pos).addClass('active'); this.pos = pos; if (this.settings.autoplay) { this.play(); } }, prev: function() { var posPrev = this.pos - 1; if (posPrev < 0) posPrev = this.numSlides - 1; this.jump( posPrev ); }, next: function() { var posNext = this.pos + 1; if (posNext >= this.numSlides) posNext = 0; this.jump( posNext ); }, play: function() { // clear any existing timer if (this.timer != null) { clearInterval(this.timer); } var self = this; this.settings.autoplay = true; // add timer this.timer = setInterval( function(){ self.next(); }, this.settings.interval ); }, stop: function() { this.settings.autoplay = false; clearInterval(this.timer); this.timer = null; } }); // A really lightweight plugin wrapper around the constructor, // preventing against multiple instantiations $.fn[ pluginName ] = function ( options ) { return this.each(function() { if ( !$.data( this, "plugin_" + pluginName ) ) { $.data( this, "plugin_" + pluginName, new Plugin( this, options ) ); } }); }; // auto create slideshow on [data-zs-enabled] instances. var $instances = $('[data-zs-src]'); if ($instances.length > 0) { $instances.each( function(index) { var $this = $(this); $this.zoomSlider(); }); } })( jQuery, window, document );