/** * Copyright (c) 2009 Anders Ekdahl (http://coffeescripter.com/) * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. * * Version: 1.1.1 * * Demo and documentation: http://coffeescripter.com/code/ad-gallery/ */ (function($) { $.fn.adGallery = function(options) { var defaults = { loader_image: '/images/gallery/navigation/loader.gif', start_at_index: 0, thumb_opacity: 0.7, animate_first_image: false, animation_speed: 400, width: false, height: false, display_next_and_prev: true, display_back_and_forward: true, scroll_jump: 0, // If 0, it jumps the width of the container animated_scroll: true, slideshow: { enable: true, autostart: false, speed: 5000, start_label: 'Start', stop_label: 'Stop', stop_on_scroll: true, countdown_prefix: '(', countdown_sufix: ')' }, effect: 'fade', // or 'slide-vert', 'fade', or 'resize', 'none', false enable_keyboard_move: true, cycle: true, callbacks: { init: false, afterImageVisible: false, beforeImageVisible: false, slideShowStart: false, slideShowStop: false } }; var settings = $.extend(defaults, options); if(!settings.slideshow.enable) { settings.slideshow.autostart = false; }; var galleries = []; $(this).each(function() { var gallery = new AdGallery(this, settings); galleries[galleries.length] = gallery; }); // Sorry, breaking the jQuery chain because the gallery instances // are returned so you can fiddle with them return galleries; }; function AdGallery(wrapper, settings) { this.init(wrapper, settings); }; AdGallery.prototype = { // Elements wrapper: false, image_wrapper: false, gallery_info: false, nav: false, loader: false, preloads: false, thumbs_wrapper: false, scroll_back: false, scroll_forward: false, next_link: false, prev_link: false, start_slideshow_link: false, stop_slideshow_link: false, slideshow_countdown: false, slideshow_controls: false, slideshow_enabled: false, slideshow_running: false, slideshow_timeout: false, slideshow_countdown_interval: false, thumbs_scroll_interval: false, image_wrapper_width: 0, image_wrapper_height: 0, current_index: 0, current_image: false, nav_display_width: 0, settings: false, images: false, in_transition: false, init: function(wrapper, settings) { var context = this; this.wrapper = $(wrapper); this.settings = settings; this.setupElements(); if(this.settings.width) { this.image_wrapper_width = this.settings.width; this.image_wrapper.width(this.settings.width); this.wrapper.width(this.settings.width); } else { this.image_wrapper_width = this.image_wrapper.width(); }; if(this.settings.height) { this.image_wrapper_height = this.settings.height; this.image_wrapper.height(this.settings.height); } else { this.image_wrapper_height = this.image_wrapper.height(); }; this.nav_display_width = this.nav.width(); this.images = []; this.current_index = 0; this.current_image = false; this.in_transition = false; this.slideshow_enabled = false; this.findImages(); if(this.settings.display_next_and_prev) { this.initNextAndPrev(); }; this.initSlideshow(); if(!this.settings.slideshow.enable) { this.disableSlideshow(); } else { this.enableSlideshow(); }; if(this.settings.display_back_and_forward) { this.initBackAndForward(); }; if(this.settings.enable_keyboard_move) { this.initKeyEvents(); }; var start_at = this.settings.start_at_index; if(window.location.hash && window.location.hash.indexOf('#ad-image') === 0) { start_at = window.location.hash.replace(/[^0-9]+/g, ''); // Check if it's a number if((start_at * 1) != start_at) { start_at = this.settings.start_at_index; }; }; this.loading(true); this.showImage(start_at, function() { // This function gets fired when the image is visible, that is, // after it has been loaded, and after some effect has made it visible // We don't want to start the slideshow before the image has been // displayed if(context.settings.slideshow.autostart) { context.preloadImage(start_at + 1); context.startSlideshow(); }; } ); if(typeof this.settings.callbacks.init == 'function') { this.settings.callbacks.init.call(this); }; }, setupElements: function() { this.controls = this.wrapper.find('.ad-controls'); this.gallery_info = $('
'); this.controls.append(this.gallery_info); this.image_wrapper = this.wrapper.find('.ad-image-wrapper'); this.image_wrapper.empty(); this.nav = this.wrapper.find('.ad-nav'); this.thumbs_wrapper = this.nav.find('.ad-thumbs'); this.preloads = $(''); this.loader = $(''+ title + desc +'
'); img_container.append(desc); }; return desc; }, /** * @param function callback Gets fired when the image has loaded and is displaying */ _showWhenLoaded: function(index, callback) { if(this.images[index]) { var context = this; var image = this.images[index]; var img_container = $(document.createElement('div')); var img = $(new Image()); img_container.addClass('ad-image'); img_container.append(img); img.attr('src', image.image); this.image_wrapper.prepend(img_container); var size = this._getContainedImageSize(image.size.width, image.size.height); var image_width = size.width; var image_height = size.height; img.attr('width', image_width); img.attr('height', image_height); img_container.css({width: image_width +'px', height: image_height +'px'}); this._centerImage(img_container, image_width, image_height); var desc = this._showDescription(image, img_container); var thumb = this.nav.find('.ad-thumb'+ index); this.highLightThumb(thumb); var direction = 'right'; if(this.current_index < index) { direction = 'left'; }; if(typeof this.settings.callbacks.beforeImageVisible == 'function') { this.settings.callbacks.beforeImageVisible.call(this, img_container, this.current_image); }; var animation_speed = this.settings.animation_speed; if(this.current_image || this.settings.animate_first_image) { var new_image_animation = {}; var old_image_animation = {}; if(this.settings.effect == 'fade') { img_container.css('opacity', 0); old_image_animation = {opacity: 0}; new_image_animation = {opacity: 1}; } else if(this.settings.effect == 'resize') { var current_left = parseInt(img_container.css('left'), 10); var current_top = parseInt(img_container.css('top'), 10); img_container.css({width: 0, height: 0, top: this.image_wrapper_height / 2, left: this.image_wrapper_width / 2}); old_image_animation = {width: 0, height: 0, top: this.image_wrapper_height / 2, left: this.image_wrapper_width / 2}; new_image_animation = {width: image_width, height: image_height, top: current_top, left: current_left}; } else if(this.settings.effect == 'slide-hori') { if(direction == 'left') { var old_image_left = '-'+ this.image_wrapper_width +'px'; var new_image_left = this.image_wrapper_width +'px'; } else { var old_image_left = this.image_wrapper_width +'px'; var new_image_left = '-'+ this.image_wrapper_width +'px'; }; var current_left = parseInt(img_container.css('left'), 10); img_container.css('left', new_image_left); old_image_animation = {left: old_image_left}; new_image_animation = {left: current_left}; if(desc) { desc.css('bottom', '-'+ desc[0].offsetHeight +'px'); desc.animate({bottom: 0}, this.settings.animation_speed * 2); }; } else if(this.settings.effect == 'slide-vert') { if(direction == 'left') { var old_image_top = '-'+ this.image_wrapper_height +'px'; var new_image_top = this.image_wrapper_height +'px'; } else { var old_image_top = this.image_wrapper_height +'px'; var new_image_top = '-'+ this.image_wrapper_height +'px'; }; var current_top = parseInt(img_container.css('top'), 10); img_container.css('top', new_image_top); old_image_animation = {top: old_image_top}; new_image_animation = {top: current_top}; if(desc) { desc.css('bottom', '-'+ desc[0].offsetHeight +'px'); desc.animate({bottom: 0}, this.settings.animation_speed * 2); }; } else if(!this.settings.effect || this.settings.effect == 'none') { old_image_animation = {opacity: 1}; new_image_animation = {opacity: 1}; animation_speed = 0; }; if(this.current_image) { var old_image = this.current_image; old_image.animate(old_image_animation, animation_speed, function() { old_image.remove(); } ); }; img_container.animate(new_image_animation, animation_speed, function() { context.current_index = index; context.current_image = img_container; context.in_transition = false; context._afterShow(); } ); } else { this.current_index = index; this.current_image = img_container; this.in_transition = false; context._afterShow(); }; if(typeof callback == 'function') { callback.call(this); }; }; }, nextIndex: function() { if(this.current_index == (this.images.length - 1)) { if(!this.settings.cycle) { return false; }; var next = 0; } else { var next = this.current_index + 1; }; return next; }, nextImage: function(callback) { var next = this.nextIndex(); if(next === false) return false; this.preloadImage(next + 1); this.showImage(next, callback); return true; }, prevIndex: function() { if(this.current_index == 0) { if(!this.settings.cycle) { return false; }; var prev = this.images.length - 1; } else { var prev = this.current_index - 1; }; return prev; }, prevImage: function(callback) { var prev = this.prevIndex(); if(prev === false) return false; this.preloadImage(prev - 1); this.showImage(prev, callback); return true; }, preloadAll: function() { var context = this; var i = 0; function preloadNext() { if(i < context.images.length) { i++; context.preloadImage(i, preloadNext); }; }; context.preloadImage(i, preloadNext); }, preloadImage: function(index, callback) { if(this.images[index]) { var image = this.images[index]; if(!this.images[index].preloaded) { var img = $(new Image()); img.attr('src', image.image); if(!this.isImageLoaded(img[0])) { this.preloads.append(img); var context = this; image.is_preloading = true; img.load( function() { image.preloaded = true; image.is_preloading = false; image.size = { width: this.width, height: this.height }; if(typeof callback == 'function') { callback.call(this); }; } ).error( function() { image.error = true; image.preloaded = false; image.is_preloading = false; image.size = false; } ); } else { image.preloaded = true; image.is_preloading = false; image.size = { width: img[0].width, height: img[0].height }; if(typeof callback == 'function') { callback.call(this); }; }; } else { if(typeof callback == 'function') { callback.call(this); }; }; }; }, isImageLoaded: function(img) { if(typeof img.complete != 'undefined' && !img.complete) { return false; }; if(typeof img.naturalWidth != 'undefined' && img.naturalWidth == 0) { return false; }; return true; }, highLightThumb: function(thumb) { this.thumbs_wrapper.find('.ad-active').removeClass('ad-active'); thumb.addClass('ad-active'); if(this.settings.thumb_opacity < 1) { this.thumbs_wrapper.find('a:not(.ad-active) img').fadeTo(300, this.settings.thumb_opacity); thumb.find('img').fadeTo(300, 1); }; var left = thumb[0].parentNode.offsetLeft; left -= (this.nav_display_width / 2) - (thumb[0].offsetWidth / 2); if(this.settings.animated_scroll) { this.thumbs_wrapper.animate({scrollLeft: left +'px'}); } else { this.thumbs_wrapper.scrollLeft(left); }; } }; })(jQuery);