// (c) 2008 Trent Foley
;(function($){document.write("<style type='text/css'>.noscript{display:none}</style>");

var ver='galleriffic-1.0';
var galleryOffset=0;
var galleries=[];
var allImages=[];
var historyCurrentHash;
var historyBackStack;
var historyForwardStack;
var isFirst=false;
var dontCheck=false;
var isInitialized=false;

function getHashFromString(hash){
	if(!hash)return-1;hash=hash.replace(/^.*#/,'');
	if(isNaN(hash))return-1;return(+hash);
}

function getHash(){
	var hash=location.hash;
	return getHashFromString(hash);
}

function registerGallery(gallery){
	galleries.push(gallery);
	galleryOffset+=gallery.data.length;
}

function getGallery(hash){
	for(i=0;i<galleries.length;i++){
		var gallery=galleries[i];
		if(hash<(gallery.data.length+gallery.offset))
		return gallery;
	}
	return 0;
}

function getIndex(gallery,hash){
	return hash-gallery.offset;
}

function clickHandler(e,gallery,link){
	gallery.pause();
	if(!gallery.settings.enableHistory){
		var hash=getHashFromString(link.href);
		if(hash>=0){
			var index=getIndex(gallery,hash);
			if(index>=0)gallery.goto(index);
		}
		e.preventDefault();
	}
}

function historyCallback(){
	var hash=getHash();
	if(hash<0)return;
		var gallery=getGallery(hash);
	if(!gallery)return;
		var index=hash-gallery.offset;gallery.goto(index);
}

function historyInit(){
	if(isInitialized)return;
	isInitialized=true;
	var current_hash=location.hash;
	historyCurrentHash=current_hash;
	if($.browser.msie){
		if(historyCurrentHash==''){
		historyCurrentHash='#';
		}
	}else if($.browser.safari){
		historyBackStack=[];
		historyBackStack.length=history.length;
		historyForwardStack=[];
		isFirst=true;
	}
	setInterval(function(){	historyCheck();},100);
}

function historyAddHistory(hash){
	historyBackStack.push(hash);
	historyForwardStack.length=0;
	isFirst=true;
}

function historyCheck(){
	if($.browser.safari){
		if(!dontCheck){
		var historyDelta=history.length-historyBackStack.length;
			if(historyDelta){
			isFirst=false;
				if(historyDelta<0){
					for(var i=0;i<Math.abs(historyDelta);i++)
						historyForwardStack.unshift(historyBackStack.pop());
				}else{
					for(var i=0;i<historyDelta;i++)
					historyBackStack.push(historyForwardStack.shift());
				}
				var cachedHash=historyBackStack[historyBackStack.length-1];
					if(cachedHash!=undefined){
						historyCurrentHash=location.hash;historyCallback();
					}
			}else if(historyBackStack[historyBackStack.length-1]==undefined&&!isFirst){
				historyCallback();
				isFirst=true;
			}
		}
	}else{
		var current_hash=location.hash;
			if(current_hash!=historyCurrentHash){
				historyCurrentHash=current_hash;
				historyCallback();
			}
	}
}

var defaults={
	delay:3000,
	numThumbs:20,
	preloadAhead:40,
	enableTopPager:false,
	enableBottomPager:true,
	imageContainerSel:'',
	captionContainerSel:'',
	controlsContainerSel:'',
	loadingContainerSel:'',
	renderSSControls:true,
	renderNavControls:true,
	playLinkText:'Play',
	pauseLinkText:'Pause',
	prevLinkText:'Previous',
	nextLinkText:'Next',
	nextPageLinkText:'Next &rsaquo;',
	prevPageLinkText:'&lsaquo; Prev',
	enableHistory:false,autoStart:false,
	onChange:undefined,
	onTransitionOut:undefined,
	onTransitionIn:undefined,
	onPageTransitionOut:undefined,
	onPageTransitionIn:undefined
	};
	
	$.fn.galleriffic=function(thumbsContainerSel,settings){
		$.extend(this,{ver:function(){return ver;},initializeThumbs:function(){
			this.data=[];
			var gallery=this;
			this.$thumbsContainer.find('ul.thumbs > li').each(function(i){
				var $li=$(this);
				var $aThumb=$li.find('a.thumb');
				var hash=gallery.offset+i;
				gallery.data.push({title:$aThumb.attr('title'),slideUrl:$aThumb.attr('href'),caption:$li.find('.caption').remove(),hash:hash});
				$aThumb.attr('rel','history');
				$aThumb.attr('href','#'+hash);
				$aThumb.click(function(e){clickHandler(e,gallery,this);});
			});
			return this;
		},
		
		isPreloadComplete:false,preloadInit:function(){
			if(this.settings.preloadAhead==0)return this;
			this.preloadStartIndex=this.currentIndex;
			var nextIndex=this.getNextIndex(this.preloadStartIndex);
			return this.preloadRecursive(this.preloadStartIndex,nextIndex);
		},
		
		preloadRelocate:function(index){this.preloadStartIndex=index;return this;},
		
		preloadRecursive:function(startIndex,currentIndex){
			if(startIndex!=this.preloadStartIndex){var nextIndex=this.getNextIndex(this.preloadStartIndex);
				return this.preloadRecursive(this.preloadStartIndex,nextIndex);
			}
		
			var gallery=this;
			var preloadCount=currentIndex-startIndex;
			if(preloadCount<0)preloadCount=this.data.length-1-startIndex+currentIndex;
			if(this.settings.preloadAhead>=0&&preloadCount>this.settings.preloadAhead){
				setTimeout(function(){gallery.preloadRecursive(startIndex,currentIndex);},500);
			return this;
			}
			
			var imageData=this.data[currentIndex];
			if(!imageData)return this;
			if(imageData.image)return this.preloadNext(startIndex,currentIndex);
			var image=new Image();
			image.onload=function(){imageData.image=this;
				gallery.preloadNext(startIndex,currentIndex);
			};
			
		image.alt=imageData.title;
		image.src=imageData.slideUrl;
		return this;
		},
			
		preloadNext:function(startIndex,currentIndex){var nextIndex=this.getNextIndex(currentIndex);
			if(nextIndex==startIndex){
				this.isPreloadComplete=true;
			}else{
				var gallery=this;
				setTimeout(function(){gallery.preloadRecursive(startIndex,nextIndex);},100);
			}
			
		return this;
		},
		
		getNextIndex:function(index){
			var nextIndex=index+1;
			if(nextIndex>=this.data.length)nextIndex=0;
				return nextIndex;
		},
		
		getPrevIndex:function(index){
			var prevIndex=index-1;
			if(prevIndex<0)prevIndex=this.data.length-1;
				return prevIndex;
		},
		
		pause:function(){
			if(this.interval)this.toggleSlideshow();
			return this;
		},
			
		play:function(){
			if(!this.interval)this.toggleSlideshow();
			return this;
		},
		
		toggleSlideshow:function(){
			if(this.interval){
				clearInterval(this.interval);
				this.interval=0;
				if(this.$controlsContainer){
					this.$controlsContainer.find('div.ss-controls a').removeClass().addClass('play').attr('title',this.settings.playLinkText).attr('href','#play').html(this.settings.playLinkText);
				}
			}else{
					this.ssAdvance();
					var gallery=this;
					this.interval=setInterval(function(){gallery.ssAdvance();},
					this.settings.delay);
					if(this.$controlsContainer){this.$controlsContainer.find('div.ss-controls a').removeClass().addClass('pause').attr('title',this.settings.pauseLinkText).attr('href','#pause').html(this.settings.pauseLinkText);
					}
			}
		return this;
		},
		
		ssAdvance:function(){var nextIndex=this.getNextIndex(this.currentIndex);
			var nextHash=this.data[nextIndex].hash;
			if(this.settings.enableHistory)location.href='#'+nextHash;
			else
			this.goto(nextIndex);return this;
		},
		
		goto:function(index){
			if(index<0)index=0;
			else if(index>=this.data.length)
				index=this.data.length-1;
					if(this.settings.onChange)
						this.settings.onChange(this.currentIndex,index);
						this.currentIndex=index;
						this.preloadRelocate(index);
			return this.refresh();
		},
		
		refresh:function(){
			var imageData=this.data[this.currentIndex];
			if(!imageData)
			return this;
			var isTransitioning=true;
			var gallery=this;
			var transitionOutCallback=function(){isTransitioning=false;
				if(gallery.$controlsContainer){
					gallery.$controlsContainer.find('div.nav-controls a.prev').attr('href','#'+gallery.data[gallery.getPrevIndex(gallery.currentIndex)].hash).end().find('div.nav-controls a.next').attr('href','#'+gallery.data[gallery.getNextIndex(gallery.currentIndex)].hash);
				}
				
				
			var imageData=gallery.data[gallery.currentIndex];
			
				if(gallery.$captionContainer){
					gallery.$captionContainer.empty().append(imageData.caption);
				}
				if(imageData.image){
					gallery.buildImage(imageData.image);
				}else{
						if(gallery.$loadingContainer){gallery.$loadingContainer.show();
						}
				}
			}
			if(this.settings.onTransitionOut){
				this.settings.onTransitionOut(transitionOutCallback);
			}else{
				this.$transitionContainers.hide();
				transitionOutCallback();
			}
			if(!imageData.image){
				var image=new Image();
				image.onload=function(){
				imageData.image=this;
					if(!isTransitioning){
						gallery.buildImage(imageData.image);
					}
				};
				image.alt=imageData.title;
				image.src=imageData.slideUrl;
			}
			this.relocatePreload=true;
			return this.syncThumbs();
			},
			
			buildImage:function(image){
				if(this.$imageContainer){
					this.$imageContainer.empty();
					var gallery=this;
					var nextIndex=this.getNextIndex(this.currentIndex);
					$('#theCurrent').text((this.currentIndex + 1) + ' Of ' + gallery.data.length);
						if(this.$loadingContainer){
							this.$loadingContainer.hide();
						}

						this.$imageContainer.append('<span class="image-wrapper"><a class="advance-link" rel="history" href="#'+this.data[nextIndex].hash+'" title="'+image.alt+'"></a></span>').find('a').append(image).click(function(e){clickHandler(e,gallery,this);});
												
				}
				if(this.settings.onTransitionIn)
					this.settings.onTransitionIn();
					else
					this.$transitionContainers.show();
				return this;
			},
			
			syncThumbs:function(){
				if(this.$thumbsContainer){
					var page=Math.floor(this.currentIndex/this.settings.numThumbs);
						if(page!=this.currentPage){
							this.currentPage=page;
							this.updateThumbs();
						}
					var $thumbs=this.$thumbsContainer.find('ul.thumbs').children();
					$thumbs.filter('.selected').removeClass('selected');
					$thumbs.eq(this.currentIndex).addClass('selected');}
				return this;
			},
			
			updateThumbs:function(){
				var gallery=this;
				var transitionOutCallback=function(){gallery.rebuildThumbs();
				if(gallery.settings.onPageTransitionIn)
					gallery.settings.onPageTransitionIn();
				else
					gallery.$thumbsContainer.show();
				};
					if(this.settings.onPageTransitionOut){
						this.settings.onPageTransitionOut(transitionOutCallback);
					}else{
						this.$thumbsContainer.hide();
						transitionOutCallback();
					}		
				return this;
			},
			
			rebuildThumbs:function(){
				if(this.currentPage<0)
					this.currentPage=0;
					var needsPagination=this.data.length>this.settings.numThumbs;
					var $topPager=this.$thumbsContainer.find('div.top');
						if($topPager.length==0)
							$topPager=this.$thumbsContainer.prepend('<div class="top paging"></div>').find('div.top');
								if(needsPagination&&this.settings.enableTopPager){$topPager.empty();
									this.buildPager($topPager);
								}
								if(needsPagination&&this.settings.enableBottomPager){
									var $bottomPager=this.$thumbsContainer.find('div.bottom');
										if($bottomPager.length==0)
											$bottomPager=this.$thumbsContainer.append('<div class="bottom paging"></div>').find('div.bottom');
										else
									$bottomPager.empty();
									this.buildPager($bottomPager);
								}
								var startIndex=this.currentPage*this.settings.numThumbs;
								var stopIndex=startIndex+this.settings.numThumbs-1;
									if(stopIndex>=this.data.length)
										stopIndex=this.data.length-1;
										var $thumbsUl=this.$thumbsContainer.find('ul.thumbs');
										$thumbsUl.find('li').each(function(i){
											var $li=$(this);
												if(i>=startIndex&&i<=stopIndex){$li.show();
												}else{
													$li.hide();
												}
										});
			$thumbsUl.removeClass('noscript');
			return this;
			},
										
			buildPager:function(pager){
				var gallery=this;
				var startIndex=this.currentPage*this.settings.numThumbs;
					if(this.currentPage>0){
						var prevPage=startIndex-this.settings.numThumbs;
						pager.append('<a class="prevPage" rel="history" href="#'+this.data[prevPage].hash+'" title="'+this.settings.prevPageLinkText+'">'+this.settings.prevPageLinkText+'</a>');
					}
					var nextPage=startIndex+this.settings.numThumbs;
					if(nextPage<this.data.length){
						pager.append('<a class="nextPage" rel="history" href="#'+this.data[nextPage].hash+'" title="'+this.settings.nextPageLinkText+'">'+this.settings.nextPageLinkText+'</a>');
					}
					pager.find('a').click(function(e){clickHandler(e,gallery,this);});return this;}});
					this.settings=$.extend({},defaults,settings);
						if(this.interval)
							clearInterval(this.interval);
							this.interval=0;
								if(this.settings.imageContainerSel)this.$imageContainer=$(this.settings.imageContainerSel);
								if(this.settings.captionContainerSel)this.$captionContainer=$(this.settings.captionContainerSel);
								if(this.settings.loadingContainerSel)this.$loadingContainer=$(this.settings.loadingContainerSel);
								this.$transitionContainers=$([]);
									if(this.$imageContainer)
										this.$transitionContainers=this.$transitionContainers.add(this.$imageContainer);
											if(this.$captionContainer)
												this.$transitionContainers=this.$transitionContainers.add(this.$captionContainer);
												this.offset=galleryOffset;
												this.$thumbsContainer=$(thumbsContainerSel);
												this.initializeThumbs();
												registerGallery(this);
												this.numPages=Math.ceil(this.data.length/this.settings.numThumbs);
												this.currentPage=-1;
												this.currentIndex=0;
												var gallery=this;
													if(this.$loadingContainer)
														this.$loadingContainer.hide();
															if(this.settings.controlsContainerSel){
															this.$controlsContainer=$(this.settings.controlsContainerSel).empty();
																if(this.settings.renderSSControls){
																	if(this.settings.autoStart){
																		this.$controlsContainer.append('<div class="ss-controls"><a href="#pause" class="pause" title="'+this.settings.pauseLinkText+'">'+this.settings.pauseLinkText+'</a></div>');
																	}else{
																		this.$controlsContainer.append('<div class="ss-controls"><a href="#play" class="play" title="'+this.settings.playLinkText+'">'+this.settings.playLinkText+'</a></div>');
																	}
																	this.$controlsContainer.find('div.ss-controls a').click(function(e){gallery.toggleSlideshow();e.preventDefault();
																	return false;
																	});
																}
																if(this.settings.renderNavControls){
																	var $navControls=this.$controlsContainer.append('<span class="current" id="theCurrent">'+ (gallery.currentIndex + 1) + ' Of ' + gallery.data.length + '</span><div class="nav-controls"><a class="prev" rel="history" title="'+this.settings.prevLinkText+'">'+this.settings.prevLinkText+'</a><a class="next" rel="history" title="'+this.settings.nextLinkText+'">'+this.settings.nextLinkText+'</a></div>').find('div.nav-controls a').click(function(e){clickHandler(e,gallery,this);});
																}
															}
															historyInit();
															var hash=getHash();
															var hashGallery=(hash>=0)?getGallery(hash):0;
															var gotoIndex=(hashGallery&&this==hashGallery)?(hash-this.offset):0;
															this.goto(gotoIndex);
															if(this.settings.autoStart){setTimeout(function(){gallery.play();},this.settings.delay);
															}
															
setTimeout(function(){gallery.preloadInit();},1000);return this;};
})(jQuery);

