				/**
				 * Overlay Gallery plugin, version: 1.0.0
				 * 
				 * Copyright (c) 2009 Tero Piirainen
				 * http://flowplayer.org/tools/overlay.html#gallery
				 *
				 * Dual licensed under MIT and GPL 2+ licenses
				 * http://www.opensource.org/licenses
				 *
				 * Since  : July 2009
				 * Date: ${date}
				 * Revision: ${revision} 
				 */
				(function($) {
					// TODO: next(), prev(), getIndex(), onChange event
					
					// version number
					var t = $.tools.overlay; 
					t.plugins = t.plugins || {};
					
					t.plugins.gallery = {
						version: '1.0.0', 
						conf: { 
							imgId: 'img',
							next: '.next',
							prev: '.prev',
							info: '.info',
							slider: '.slider',
							progress: '.progress',
							disabledClass: 'disabled',
							activeClass: 'active',
							opacity: 0.8,
							speed: 'slow',
							template: '<strong>${title}</strong> <span>Image ${index} of ${total}</span>',  
							autohide: true,
							preload: true,
							api: false
						}
					};			

					$.fn.gallery = function(opts) {
						
						var conf = $.extend({}, t.plugins.gallery.conf), api;
						$.extend(conf, opts);   	

						// common variables for all gallery images
						api = this.overlay();
						
						var links = this,
							 overlay = api.getOverlay(),
							 next = overlay.find(conf.next),
							 prev = overlay.find(conf.prev),
							 info = overlay.find(conf.info),
							 slider = overlay.find(conf.slider),
							 progress = overlay.find(conf.progress),
							 els = prev.add(next).add(info).css({opacity: conf.opacity}),
							 close = api.getClosers(), 			 
							 index;
						
						
				//{{{ load 

						function load(el) {
							progress.fadeIn();
							els.hide(); close.hide();

							loadImage(el, overlay);
													
							if (conf.preload) {
								links.filter(":eq(" +(index-1)+ "), :eq(" +(index+1)+ ")").each(function()  {
									var img = new Image();
									img.src = $(this).attr("href");					
								});
							}
							
						}
						
				//}}}

						function loadImage(el, animateElem) {
							var url = el.attr("href"); 
							
							// download the image 
							var image = new Image();
							
							image.onload = function() {
								progress.fadeOut();
								
								// find image inside overlay
								var img = $("#" + conf.imgId, overlay); 
								
								// or append it to the overlay 
								if (!img.length) { 
									img = $("<img/>").attr("id", conf.imgId).css("visibility", "hidden");
									overlay.prepend(img);
								}
								
								// make initially invisible to get it's dimensions
								img.attr("src", url).css("visibility", "hidden"); 			
									
								// animate overlay to fit the image dimensions
								var width = image.width;
								var left = ($(window).width() - width) / 2;
									
								// calculate index number
								index = links.index(links.filter("[href=" +url+ "]"));	
								
								// activate trigger
								links.removeClass(conf.activeClass).eq(index).addClass(conf.activeClass);
								
								// enable/disable next/prev links
								var cls = conf.disabledClass;
								els.removeClass(cls);

								if (index === 0) { prev.addClass(cls); }
								if (index == links.length -1) { next.addClass(cls); }
								
								
								// set info text & width
								var text = conf.template
									.replace("${title}", el.attr("title") || el.data("title"))
									.replace("${index}", index + 1)
									.replace("${total}", links.length);
									
								var padd = parseInt(info.css("paddingLeft"), 10) +  parseInt(info.css("paddingRight"), 10);
								info.html(text).css({width: width - padd});				

								if( slider ) {
									slider.css('width', image.width).show();
									// rescale visable image count
									var sapi = slider.scrollable({api: true});
									var selectedItem = sapi.getClickIndex();
									var visibleSize = $('.slider').innerWidth() / sapi.getItems().eq(0).outerWidth(true);
									sapi.getConf().size = parseInt(visibleSize);
									if( sapi.getConf().size > sapi.getItems().size() ) sapi.begin(); 
									else sapi.seekTo(selectedItem);
								}
								
								overlay.animate({
									width: width, height: image.height, left: left}, conf.speed, function() {
									// gradually show the image
									img.hide();
									img.css("visibility", "visible").fadeIn(function() {
										if (!conf.autohide) { 
											els.fadeIn(); close.show(); 
										}														
									});
								});
							};
							
							image.onerror = function() {
								overlay.fadeIn().html("Cannot find image " + url); 
							};
							
							image.src = url;							
						}


						// function to add click handlers to next/prev links	 
						function addClick(el, isNext)  {
							
							el.click(function() {
									
								if (el.hasClass(conf.disabledClass)) { return; }				
								
								// find the triggering link
								var trigger = links.eq(i = index + (isNext ? 1 : -1));			
									 
								// if found load it's href
								if (trigger.length) { loadImage(trigger); }
								
								if( slider ) {
									slider.find('img').removeClass('active').eq(i).addClass('active');
								}
								
							});				
						}

						// assign next/prev click handlers
						addClick(next, true);
						addClick(prev);

						
						// arrow keys
						$(document).keydown(function(evt) {
								
							if (!overlay.is(":visible") || evt.altKey || evt.ctrlKey) { return; }
							
							if (evt.keyCode == 37 || evt.keyCode == 39) {					
								var btn = evt.keyCode == 37 ? prev : next;
								btn.click();
								return evt.preventDefault();
							}	
							return true;			
						});		
						
						function showEls() {
							if (!overlay.is(":animated")) {
								els.show(); close.show();		
							}	
						}
						
						// autohide functionality
						if (conf.autohide) { 
							overlay.hover(showEls, function() { els.fadeOut();	close.hide(); }).mousemove(showEls);
						}		
						
						// load a proper gallery image when overlay trigger is clicked
						var ret;

						 
						this.each(function() {
								
							var el = $(this), api = $(this).overlay(), ret = api;
							
							api.onBeforeLoad(function() {
								load(el);
							});
							
							api.onClose(function() {
								links.removeClass(conf.activeClass);	
							});
						});

						if( slider ) {			// init slider from images list
							if( slider.find('.items').size() == 0 ) slider.append('<div class="items"></div>');
							// slider.css('position', 'relative').css('overflow', 'hidden').css('width', '100%');
						 
							var sliderItems = slider.find('.items');
							this.each(function() {
								var el = $(this);
								var image = el.find('img').clone();
								 
								image.click(function() {
									loadImage(el);
								});
								sliderItems.append(image);
							
							});
							// sliderItems.css('position', 'absolute').css('width', '20000em');
							
							slider.scrollable();
						}
						
						return conf.api ? ret : this;
						
					};
					
				})(jQuery);	

