(function(window, $, undefined) { /* * smartresize: debounced resize event for jQuery * * latest version and complete README available on Github: * https://github.com/louisremi/jquery.smartresize.js * * Copyright 2011 @louis_remi * Licensed under the MIT license. */ 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-left', 50 + 'px') .stop() .delay(this.options.speed * this.options.titlesFactor) .animate({marginLeft: 0 + 'px', opacity: 1}, this.options.titlespeed, this.options.titleeasing) .end() .find('div.ei-title > h3') .css('margin-left', -50 + 'px') .stop() .delay(this.options.speed * this.options.titlesFactor) .animate({marginLeft: 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);