/* * jQuery gallerificPlus plugin * * Copyright (c) 2008 Matt Gifford (http://www.mattgifford.co.uk) * Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike License * http://creativecommons.org/licenses/by-nc-sa/3.0/ * * Thanks to Trent Foley (Gallerific plugin author - http://www.twospy.com)  * and Leandro Vieira Pinho (jQuery Lightbox plugin author - http://leandrovieira.com), whose amazing plugins I adapted and integrated to work together. * I wouldn't have had anything to work with if it wasn't for those guys, so thank you very VERY much. */;(function($) {	// Write noscript style	document.write("<style type='text/css'>.noscript{display:none}</style>");	var ver = 'gallerifficPlus0.3';	var galleryOffset = 0;	var galleries = [];	var allImages = [];		var historyCurrentHash;	var historyBackStack;	var historyForwardStack;	var isFirst = false;	var dontCheck = false;	var isInitialized = false;	function getHash() {		var hash = location.hash;		if (!hash) return -1;		hash = hash.replace(/^.*#/, '');		if (isNaN(hash)) return -1;		return (+hash);	}	function registerGallery(gallery) {		galleries.push(gallery);				// update the global offset value		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 historyCallback() {		// Using present location.hash always (seems to work, unlike the hash argument passed to this callback)		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) {			// To stop the callback firing twice during initilization if no hash present			if (historyCurrentHash == '') {				historyCurrentHash = '#';			}		} else if ($.browser.safari) {			// etablish back/forward stacks			historyBackStack = [];			historyBackStack.length = history.length;			historyForwardStack = [];			isFirst = true;		}		setInterval(function() { historyCheck(); }, 100);	}		function historyAddHistory(hash) {		// This makes the looping function do something		historyBackStack.push(hash);		historyForwardStack.length = 0; // clear forwardStack (true click occured)		isFirst = true;	}		function historyCheck() {		if ($.browser.safari) {			if (!dontCheck) {				var historyDelta = history.length - historyBackStack.length;								if (historyDelta) { // back or forward button has been pushed					isFirst = false;					if (historyDelta < 0) { // back button has been pushed						// move items to forward stack						for (var i = 0; i < Math.abs(historyDelta); i++) historyForwardStack.unshift(historyBackStack.pop());					} else { // forward button has been pushed						// move items to back stack						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 {			// otherwise, check for location.hash			var current_hash = location.hash;			if(current_hash != historyCurrentHash) {				historyCurrentHash = current_hash;				historyCallback();			}		}	}	var defaults = {		delay:                3000,		numThumbs:            20,		preloadAhead:         40, // Set to -1 to preload all images		enableTopPager:       true,		enableBottomPager:    true,		imageContainerSel:    '',		thumbsContainerSel:   '',		controlsContainerSel: '',		titleContainerSel:    '',		descContainerSel:     '',		downloadLinkSel:      '',		renderSSControls:     true,		renderNavControls:    true,		playLinkText:         'Play',		pauseLinkText:        'Pause',		prevLinkText:         'Previous',		nextLinkText:         'Next',		nextPageLinkText:     'Next &rsaquo;',		prevPageLinkText:     '&lsaquo; Prev',		autoPlay:			  true,				// Configuration related to overlay		overlayBgColor: 		'#000',		// (string) Background color to overlay; inform a hexadecimal value like: #RRGGBB. Where RR, GG, and BB are the hexadecimal values for the red, green, and blue values of the color.		overlayOpacity:			0.8,		// (integer) Opacity value to overlay; inform: 0.X. Where X are number from 0 to 9		// Configuration related to navigation		fixedNavigation:		false,		// (boolean) Boolean that informs if the navigation (next and prev button) will be fixed or not in the interface.		// Configuration related to images		imageLoading:			'assets/images/projects/lightbox-ico-loading.gif',		// (string) Path and the name of the loading icon		imageBtnPrev:			'assets/images/projects/lightbox-btn-prev.gif',			// (string) Path and the name of the prev button image		imageBtnNext:			'assets/images/projects/lightbox-btn-next.gif',			// (string) Path and the name of the next button image		imageBtnClose:			'assets/images/projects/lightbox-btn-close.gif',		// (string) Path and the name of the close btn		imageBlank:				'assets/images/projects/lightbox-blank.gif',			// (string) Path and the name of a blank image (one pixel)		// Configuration related to container image box		containerBorderSize:	10,			// (integer) If you adjust the padding in the CSS for the container, #lightbox-container-image-box, you will need to update this value		containerResizeSpeed:	400,		// (integer) Specify the resize duration of container image. These number are miliseconds. 400 is default.		// Configuration related to texts in caption. For example: Image 2 of 8. You can alter either "Image" and "of" texts.		txtImage:				'Image',	// (string) Specify text "Image"		txtOf:					'of',		// (string) Specify text "of"		// Configuration related to keyboard navigation		keyToClose:				'c',		// (string) (c = close) Letter to close the jQuery lightBox interface. Beyond this letter, the letter X and the SCAPE key is used to.		keyToPrev:				'p',		// (string) (p = previous) Letter to show the previous image		keyToNext:				'n',		// (string) (n = next) Letter to show the next image.		// Don´t alter these variables in any way		imageArray:				[],		activeImage:			0,		// Allow keyboard navigation on gallery as well as lightbox?		galleryKeyboardNav:		true		// (boolean) Boolean that informs if the keyboard navigation will be used with the gallery (as it is used with the lightbox).			};		// lightbox specific functions		function buildLightBox(image,gallery,current) {			gallery.pause();				// Hide some elements to avoid conflict with overlay in IE. These elements appear above the overlay.		$('embed, object, select').css({ 'visibility' : 'hidden' });		// Call the function to create the markup structure; style some elements; assign events in some elements.		_set_interface();		// Unset total images in imageArray		defaults.imageArray.length = 0;		// Unset image active information		defaults.activeImage = 0;				if ( gallery.data.length == 1 ) {			defaults.imageArray.push(new Array(gallery.data[current].original,gallery.data[current].title));		} else {			// Add an Array (as many as we have), with href and title atributes, inside the Array that storage the images references					for ( var i = 0; i < gallery.data.length; i++ ) {				defaults.imageArray.push(new Array(gallery.data[i].original,gallery.data[i].title));			}		}		while ( defaults.imageArray[defaults.activeImage][0] != gallery.data[current].original ) {			defaults.activeImage++;		}		// Call the function that prepares image exibition		_set_image_to_view();	}		/**	 * Create the jQuery lightBox plugin interface	 *	 * The HTML markup will be like that:		<div id="jquery-overlay"></div>		<div id="jquery-lightbox">			<div id="lightbox-container-image-box">				<div id="lightbox-container-image">					<img src="../fotos/XX.jpg" id="lightbox-image">					<div id="lightbox-nav">						<a href="#" id="lightbox-nav-btnPrev"></a>						<a href="#" id="lightbox-nav-btnNext"></a>					</div>					<div id="lightbox-loading">						<a href="#" id="lightbox-loading-link">							<img src="../images/lightbox-ico-loading.gif">						</a>					</div>				</div>			</div>			<div id="lightbox-container-image-data-box">				<div id="lightbox-container-image-data">					<div id="lightbox-image-details">						<span id="lightbox-image-details-caption"></span>						<span id="lightbox-image-details-currentNumber"></span>					</div>					<div id="lightbox-secNav">						<a href="#" id="lightbox-secNav-btnClose">							<img src="../images/lightbox-btn-close.gif">						</a>					</div>				</div>			</div>		</div>	 *	 */	function _set_interface() {		// Apply the HTML markup into body tag		$('body').append('<div id="jquery-overlay"></div><div id="jquery-lightbox"><div id="lightbox-container-image-box"><div id="lightbox-container-image"><img id="lightbox-image"><div style="" id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="' + defaults.imageLoading + '"></a></div></div></div><div id="lightbox-container-image-data-box"><div id="lightbox-container-image-data"><div id="lightbox-image-details"><span id="lightbox-image-details-caption"></span><span id="lightbox-image-details-currentNumber"></span></div><div id="lightbox-secNav"><a href="#" id="lightbox-secNav-btnClose"><img src="' + defaults.imageBtnClose + '"></a></div></div></div></div>');			// Get page sizes		var arrPageSizes = ___getPageSize();		// Style overlay and show it		$('#jquery-overlay').css({			backgroundColor:	defaults.overlayBgColor,			opacity:			defaults.overlayOpacity,			width:				arrPageSizes[0],			height:				arrPageSizes[1]		}).fadeIn();		// Get page scroll		var arrPageScroll = ___getPageScroll();		// Calculate top and left offset for the jquery-lightbox div object and show it		$('#jquery-lightbox').css({			top:	arrPageScroll[1] + (arrPageSizes[3] / 10),			left:	arrPageScroll[0]		}).show();		// Assigning click events in elements to close overlay		$('#jquery-overlay,#jquery-lightbox').click(function() {			_finish();											});		// Assign the _finish function to lightbox-loading-link and lightbox-secNav-btnClose objects		$('#lightbox-loading-link,#lightbox-secNav-btnClose').click(function() {			_finish();			return false;		});		// If window was resized, calculate the new overlay dimensions		$(window).resize(function() {			// Get page sizes			var arrPageSizes = ___getPageSize();			// Style overlay and show it			$('#jquery-overlay').css({				width:		arrPageSizes[0],				height:		arrPageSizes[1]			});			// Get page scroll			var arrPageScroll = ___getPageScroll();			// Calculate top and left offset for the jquery-lightbox div object and show it			$('#jquery-lightbox').css({				top:	arrPageScroll[1] + (arrPageSizes[3] / 10),				left:	arrPageScroll[0]			});		});	}			/**	 * Prepares image exibition; doing a image´s preloader to calculate it´s size	 *	 */	function _set_image_to_view() { // show the loading		// Show the loading		$('#lightbox-loading').show();		if ( defaults.fixedNavigation ) {			$('#lightbox-image,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();		} else {			// Hide some elements			$('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();		}		// Image preload process		var objImagePreloader = new Image();		objImagePreloader.onload = function() {			$('#lightbox-image').attr('src',defaults.imageArray[defaults.activeImage][0]);			// Perfomance an effect in the image container resizing it			_resize_container_image_box(objImagePreloader.width,objImagePreloader.height);			//	clear onLoad, IE behaves irratically with animated gifs otherwise			objImagePreloader.onload=function(){};		};		objImagePreloader.src = defaults.imageArray[defaults.activeImage][0];	};		/**	 * Perfomance an effect in the image container resizing it	 *	 * @param integer intImageWidth The image´s width that will be showed	 * @param integer intImageHeight The image´s height that will be showed	 */	function _resize_container_image_box(intImageWidth,intImageHeight) {		// Get current width and height		var intCurrentWidth = $('#lightbox-container-image-box').width();		var intCurrentHeight = $('#lightbox-container-image-box').height();		// Get the width and height of the selected image plus the padding		var intWidth = (intImageWidth + (defaults.containerBorderSize * 2)); // Plus the image´s width and the left and right padding value		var intHeight = (intImageHeight + (defaults.containerBorderSize * 2)); // Plus the image´s height and the left and right padding value		// Diferences		var intDiffW = intCurrentWidth - intWidth;		var intDiffH = intCurrentHeight - intHeight;		// Perfomance the effect		$('#lightbox-container-image-box').animate({ width: intWidth, height: intHeight },defaults.containerResizeSpeed,function() { _show_image(); });		if ( ( intDiffW == 0 ) && ( intDiffH == 0 ) ) {			if ( $.browser.msie ) {				___pause(250);			} else {				___pause(100);				}		} 		$('#lightbox-container-image-data-box').css({ width: intImageWidth });		$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({ height: intImageHeight + (defaults.containerBorderSize * 2) });	};		/**	 * Show the prepared image	 *	 */	function _show_image() {		$('#lightbox-loading').hide();		$('#lightbox-image').fadeIn(function() {			_show_image_data();			_set_navigation();		});		_preload_neighbor_images();	};		/**	 * Show the image information	 *	 */	function _show_image_data() {		$('#lightbox-container-image-data-box').slideDown('fast');		$('#lightbox-image-details-caption').hide();		if ( defaults.imageArray[defaults.activeImage][1] ) {			$('#lightbox-image-details-caption').html(defaults.imageArray[defaults.activeImage][1]).show();		}		// If we have a image set, display 'Image X of X'		if ( defaults.imageArray.length > 1 ) {			$('#lightbox-image-details-currentNumber').html(defaults.txtImage + ' ' + ( defaults.activeImage + 1 ) + ' ' + defaults.txtOf + ' ' + defaults.imageArray.length).show();		}			}		// handles the reloaction of the URL hash variable when the previous/next buttons are clicked within the lightbox UI.	function changeThumbnail(activeImg) {		location.href = '#'+activeImg;		// IE we need to explicity call goto		/*if ($.browser.msie) {			this.goto(activeImg);		}*/	}		/**	 * Display the button navigations	 *	 */	function _set_navigation() {		$('#lightbox-nav').show();		// Instead to define this configuration in CSS file, we define here. And it´s need to IE. Just.		$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({ 'background' : 'transparent url(' + defaults.imageBlank + ') no-repeat' });				// Show the prev button, if not the first image in set		if ( defaults.activeImage != 0 ) {			if ( defaults.fixedNavigation ) {				$('#lightbox-nav-btnPrev').css({ 'background' : 'url(' + defaults.imageBtnPrev + ') left 15% no-repeat' })					.unbind()					.bind('click',function() {						defaults.activeImage = defaults.activeImage - 1;						changeThumbnail();						_set_image_to_view();						return false;					});			} else {				// Show the images button for Next buttons				$('#lightbox-nav-btnPrev').unbind().hover(function() {					$(this).css({ 'background' : 'url(' + defaults.imageBtnPrev + ') left 15% no-repeat' });				},function() {					$(this).css({ 'background' : 'transparent url(' + defaults.imageBlank + ') no-repeat' });				}).show().bind('click',function() {					defaults.activeImage = defaults.activeImage - 1;					changeThumbnail(defaults.activeImage);					_set_image_to_view();					return false;				});			}		}				// Show the next button, if not the last image in set		if ( defaults.activeImage != ( defaults.imageArray.length -1 ) ) {			if ( defaults.fixedNavigation ) {				$('#lightbox-nav-btnNext').css({ 'background' : 'url(' + defaults.imageBtnNext + ') right 15% no-repeat' })					.unbind()					.bind('click',function() {						defaults.activeImage = defaults.activeImage + 1;						changeThumbnail(defaults.activeImage);						_set_image_to_view();						return false;					});			} else {				// Show the images button for Next buttons				$('#lightbox-nav-btnNext').unbind().hover(function() {					$(this).css({ 'background' : 'url(' + defaults.imageBtnNext + ') right 15% no-repeat' });				},function() {					$(this).css({ 'background' : 'transparent url(' + defaults.imageBlank + ') no-repeat' });				}).show().bind('click',function() {					defaults.activeImage = defaults.activeImage + 1;					changeThumbnail(defaults.activeImage);					_set_image_to_view();					return false;				});			}		}		// Enable keyboard navigation		_enable_keyboard_navigation();	}		/**	 * Enable a support to keyboard navigation	 *	 */	function _enable_keyboard_navigation() {		$(document).keydown(function(objEvent) {			_keyboard_action(objEvent);		});	}	/**	 * Disable the support to keyboard navigation	 *	 */	function _disable_keyboard_navigation() {		$(document).unbind();	}			/**	 * Perform the keyboard actions	 *	 */	function _keyboard_action(objEvent) {		// To ie		if ( objEvent == null ) {			keycode = event.keyCode;			escapeKey = 27;		// To Mozilla		} else {			keycode = objEvent.keyCode;			escapeKey = objEvent.DOM_VK_ESCAPE;		}		// Get the key in lower case form		key = String.fromCharCode(keycode).toLowerCase();		// Verify the keys to close the ligthBox		if ( ( key == defaults.keyToClose ) || ( key == 'x' ) || ( keycode == escapeKey ) ) {			_finish();		}		// Verify the key to show the previous image		if ( ( key == defaults.keyToPrev ) || ( keycode == 37 ) ) {			// If we´re not showing the first image, call the previous			if ( defaults.activeImage != 0 ) {				defaults.activeImage = defaults.activeImage - 1;				changeThumbnail(defaults.activeImage);				_set_image_to_view();				_disable_keyboard_navigation();			}		}		// Verify the key to show the next image		if ( ( key == defaults.keyToNext ) || ( keycode == 39 ) ) {			// If we´re not showing the last image, call the next			if ( defaults.activeImage != ( defaults.imageArray.length - 1 ) ) {				defaults.activeImage = defaults.activeImage + 1;				changeThumbnail(defaults.activeImage);				_set_image_to_view();				_disable_keyboard_navigation();			}		}	}	/**	 * Preload prev and next images being showed	 *	 */	function _preload_neighbor_images() {		if ( (defaults.imageArray.length -1) > defaults.activeImage ) {			objNext = new Image();			objNext.src = defaults.imageArray[defaults.activeImage + 1][0];		}		if ( defaults.activeImage > 0 ) {			objPrev = new Image();			objPrev.src = defaults.imageArray[defaults.activeImage -1][0];		}	}	/**	 * Remove jQuery lightBox plugin HTML markup	 *	 */	function _finish() {		$('#jquery-lightbox').remove();		$('#jquery-overlay').fadeOut(function() { $('#jquery-overlay').remove(); });		// Show some elements to avoid conflict with overlay in IE. These elements appear above the overlay.		$('embed, object, select').css({ 'visibility' : 'visible' });	}	/**	 / THIRD FUNCTION	 * getPageSize() by quirksmode.com	 *	 * @return Array Return an array with page width, height and window width, height	 */	function ___getPageSize() {		var xScroll, yScroll;		if (window.innerHeight && window.scrollMaxY) {				xScroll = window.innerWidth + window.scrollMaxX;			yScroll = window.innerHeight + window.scrollMaxY;		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac			xScroll = document.body.scrollWidth;			yScroll = document.body.scrollHeight;		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari			xScroll = document.body.offsetWidth;			yScroll = document.body.offsetHeight;		}		var windowWidth, windowHeight;		if (self.innerHeight) {	// all except Explorer			if(document.documentElement.clientWidth){				windowWidth = document.documentElement.clientWidth; 			} else {				windowWidth = self.innerWidth;			}			windowHeight = self.innerHeight;		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode			windowWidth = document.documentElement.clientWidth;			windowHeight = document.documentElement.clientHeight;		} else if (document.body) { // other Explorers			windowWidth = document.body.clientWidth;			windowHeight = document.body.clientHeight;		}			// for small pages with total height less then height of the viewport		if(yScroll < windowHeight){			pageHeight = windowHeight;		} else { 			pageHeight = yScroll;		}		// for small pages with total width less then width of the viewport		if(xScroll < windowWidth){				pageWidth = xScroll;				} else {			pageWidth = windowWidth;		}		arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight);		return arrayPageSize;	};	/**	 / THIRD FUNCTION	 * getPageScroll() by quirksmode.com	 *	 * @return Array Return an array with x,y page scroll values.	 */	function ___getPageScroll() {		var xScroll, yScroll;		if (self.pageYOffset) {			yScroll = self.pageYOffset;			xScroll = self.pageXOffset;		} else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict			yScroll = document.documentElement.scrollTop;			xScroll = document.documentElement.scrollLeft;		} else if (document.body) {// all other Explorers			yScroll = document.body.scrollTop;			xScroll = document.body.scrollLeft;			}		arrayPageScroll = new Array(xScroll,yScroll);		return arrayPageScroll;	};	 /**	  * Stop the code execution from a escified time in milisecond	  *	  */	 function ___pause(ms) {		var date = new Date(); 		curDate = null;		do { var curDate = new Date(); }		while ( curDate - date < ms);	 };		// end of lightbox functions		function clickHandler(gallery) {		gallery.pause();		return false;	}	$.fn.galleriffic = function(thumbsContainerSel, settings) {		//  Extend Gallery Object		$.extend(this, {			ver: function() {				return ver;			},			buildDataFromThumbs: function() {				this.data = [];				var gallery = this;				this.$thumbsContainer.find('li').each(function(i) {					var $a = $(this).find('a');					var $img = $a.find('img:first');					gallery.data.push({slide:$a.attr('href'),thumb:$img.attr('src'),original:$a.attr('original'),title:$a.attr('title'),description:$a.attr('description'),hash:gallery.offset+i});				});				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) {				// By changing this startIndex, the current preload script will restart				this.preloadStartIndex = index;				return this;			},			preloadRecursive: function(startIndex, currentIndex) {				// Check if startIndex has been relocated				if (startIndex != this.preloadStartIndex) {					var nextIndex = this.getNextIndex(this.preloadStartIndex);					return this.preloadRecursive(this.preloadStartIndex, nextIndex);				}				var gallery = this;				// Now check for preloadAhead count				var preloadCount = currentIndex - startIndex;				if (preloadCount < 0)					preloadCount = this.data.length-1-startIndex+currentIndex;				if (this.settings.preloadAhead >= 0 && preloadCount > this.settings.preloadAhead) {					// Do this in order to keep checking for relocated start index					setTimeout(function() { gallery.preloadRecursive(startIndex, currentIndex); }, 500);					return this;				}				var imageData = this.data[currentIndex];				// If already loaded, continue				if (imageData.$image)					return this.preloadNext(startIndex, currentIndex); 								// Preload the image				var image = new Image();								image.onload = function() {					imageData.$image = this;					gallery.preloadNext(startIndex, currentIndex);				};				image.alt = imageData.title;				image.src = imageData.slide;				return this;			},						preloadNext: function(startIndex, currentIndex) {				var nextIndex = this.getNextIndex(currentIndex);				if (nextIndex == startIndex) {					this.isPreloadComplete = true;				} else {					// Use set timeout to free up thread					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 span').removeClass().addClass('play')							.attr('title', this.settings.playLinkText)							.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 span').removeClass().addClass('pause')							.attr('title', this.settings.pauseLinkText)							.html(this.settings.pauseLinkText);					}				}				return this;			},			ssAdvance: function() {				var nextIndex = this.getNextIndex(this.currentIndex);				var nextHash = this.data[nextIndex].hash;								// Seems to be working on both FF and Safari				location.href = '#'+nextHash;				// IE we need to explicity call goto				if ($.browser.msie) {					this.goto(nextIndex);				}				return this;			},			goto: function(index) {				if (index < 0) index = 0;				else if (index >= this.data.length) index = this.data.length-1;				this.currentIndex = index;				this.preloadRelocate(index);				return this.refresh();			},						refresh: function() {				if (this.$imageContainer) {					var imageData = this.data[this.currentIndex];					var isFading = 1;					var gallery = this;					// hide img					this.$imageContainer.fadeOut('fast', function() {						isFading = 0;						// Update Controls						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);						}						// Replace Title						if (gallery.$titleContainer) {							gallery.$titleContainer.empty().html(imageData.title);						}						// Replace Description						if (gallery.$descContainer) {							gallery.$descContainer.empty().html(imageData.description);						}						// Update Download Link						if (gallery.$downloadLink) {							gallery.$downloadLink.attr('href', imageData.original);						}						if (imageData.$image) {							gallery.buildImage(imageData.$image);						}					});										if (this.onFadeOut) this.onFadeOut();					if (!imageData.$image) {						var image = new Image();						// Wire up mainImage onload event						image.onload = function() {							imageData.$image = this;							if (!isFading) {								gallery.buildImage(imageData.$image);							}						};						// set alt and src						image.alt = imageData.title;						image.src = imageData.slide;					}					// This causes the preloader (if still running) to relocate out from the currentIndex					this.relocatePreload = true;				}				return this.syncThumbs();			},						buildImage: function(image) {				if (this.$imageContainer) {					this.$imageContainer.empty();					var gallery = this;										var thisImageIndex = this.currentIndex;					// Setup image					this.$imageContainer						//.append('<span class="image-wrapper"><a class="advance-link" rel="history" href="#'+this.data[this.getNextIndex(this.currentIndex)].hash+'" title="'+image.alt+'"></a></span>')						.append('<span class="image-wrapper"><a class="advance-link" rel="history" title="'+image.alt+'"></a></span>')						.find('a')						.append(image)						//.click(function() { clickHandler(gallery); })						.click(function() { buildLightBox(image,gallery,thisImageIndex); })						.end()						.fadeIn('fast');										if (this.onFadeIn) this.onFadeIn();				}				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();					} else {						var selectedThumb = this.currentIndex % this.settings.numThumbs;						// Remove existing selected class and add selected class to new thumb						this.$thumbsContainer							.find('ul.thumbs li.selected')							.removeClass('selected')							.end()							//.find('ul.thumbs a[href="#'+this.currentIndex+'"]')							.find('ul.thumbs li').eq(selectedThumb)							.addClass('selected');					}				}				return this;			},			updateThumbs: function() {				if (this.$thumbsContainer) {					// Initialize currentPage to first page					if (this.currentPage < 0)						this.currentPage = 0;									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 needsPagination = this.data.length > this.settings.numThumbs;					// Clear thumbs container					this.$thumbsContainer.empty();									// Rebuild top pager					this.$thumbsContainer.append('<div class="top pagination"></div>');					if (needsPagination && this.settings.enableTopPager) {						this.buildPager(this.$thumbsContainer.find('div.top'));					}					// Rebuild thumbs					var $ulThumbs = this.$thumbsContainer.append('<ul class="thumbs"></ul>').find('ul.thumbs');					for (i=startIndex; i<=stopIndex; i++) {						var selected = '';											if (i==this.currentIndex)							selected = ' class="selected"';												var imageData = this.data[i];						$ulThumbs.append('<li'+selected+'><a rel="history" href="#'+imageData.hash+'" title="'+imageData.title+'"><img src="'+imageData.thumb+'" alt="'+imageData.title+'" /></a></li>');					}					// Rebuild bottom pager					if (needsPagination && this.settings.enableBottomPager) {						this.$thumbsContainer.append('<div class="bottom pagination"></div>');						this.buildPager(this.$thumbsContainer.find('div.bottom'));					}					// Add click handlers					var gallery = this;					this.$thumbsContainer.find('a[rel="history"]').click(function() { clickHandler(gallery); });				}				return this;			},			buildPager: function(pager) {				var startIndex = this.currentPage*this.settings.numThumbs;								// Prev Page Link				if (this.currentPage > 0) {					var prevPage = startIndex - this.settings.numThumbs;					pager.append('<a rel="history" href="#'+this.data[prevPage].hash+'" title="'+this.settings.prevPageLinkText+'">'+this.settings.prevPageLinkText+'</a>');				}								// Page Index Links				for (i=this.currentPage-3; i<=this.currentPage+3; i++) {					var pageNum = i+1;										if (i == this.currentPage)						pager.append('<strong>'+pageNum+'</strong>');					else {						var imageIndex = i*this.settings.numThumbs;						if (i>=0 && i<this.numPages) {							pager.append('<a rel="history" href="#'+this.data[imageIndex].hash+'" title="'+pageNum+'">'+pageNum+'</a>');						}					}				}								// Next Page Link				var nextPage = startIndex+this.settings.numThumbs;				if (nextPage < this.data.length) {					pager.append('<a rel="history" href="#'+this.data[nextPage].hash+'" title="'+this.settings.nextPageLinkText+'">'+this.settings.nextPageLinkText+'</a>');				}								return this;			}		});		// Now initialize the gallery		this.settings = $.extend({}, defaults, settings);				if (this.settings.galleryKeyboardNav) {			_enable_keyboard_navigation();		}		if (this.interval)			clearInterval(this.interval);		this.interval = 0;				if (this.settings.imageContainerSel) this.$imageContainer = $(this.settings.imageContainerSel);		if (this.settings.thumbsContainerSel) this.$thumbsContainer = $(this.settings.thumbsContainerSel);		if (this.settings.titleContainerSel) this.$titleContainer = $(this.settings.titleContainerSel);		if (this.settings.descContainerSel) this.$descContainer = $(this.settings.descContainerSel);		if (this.settings.downloadLinkSel) this.$downloadLink = $(this.settings.downloadLinkSel);		// Set the hash index offset for this gallery		this.offset = galleryOffset;		// This is for backward compatibility		if (thumbsContainerSel instanceof Array) {			this.data = thumbsContainerSel;		} else {			this.$thumbsContainer = $(thumbsContainerSel);			this.buildDataFromThumbs();		}				// Add this gallery to the global galleries array		registerGallery(this);		this.numPages = Math.ceil(this.data.length/this.settings.numThumbs);		this.currentPage = -1;		this.currentIndex = 0;		var gallery = this;		// Setup controls		if (this.settings.controlsContainerSel) {			this.$controlsContainer = $(this.settings.controlsContainerSel).empty();						if (this.settings.renderSSControls) {				this.$controlsContainer					.append('<div class="ss-controls"><span class="play" title="'+this.settings.playLinkText+'">'+this.settings.playLinkText+'</span></div>')					.find('div.ss-controls span')					.click(function() { gallery.toggleSlideshow(); });			}					if (this.settings.renderNavControls) {									this.$controlsContainer					.append('<div class="nav-controls"><a class="prev" rel="history" title="'+this.settings.prevLinkText+'">'+this.settings.prevLinkText+'</a><a class="next" rel="history" title="Next">'+this.settings.nextLinkText+'</a></div>')					.find('a[rel="history"]')					.click(function() { clickHandler(gallery); });			}		}		// Initialize history only once when the first gallery on the page is initialized		historyInit();		// Build image		var hash = getHash();		var hashGallery = (hash >= 0) ? getGallery(hash) : 0;		var gotoIndex = (hashGallery && this == hashGallery) ? (hash-this.offset) : 0;		this.goto(gotoIndex);		// Kickoff Image Preloader after 1 second		setTimeout(function() { gallery.preloadInit(); }, 1000);				// autoplay  - run the transitions as soon as the gallery has been loaded if autoPlay is true		if(this.settings.autoPlay) {			gallery.play();		}				return this;	};})(jQuery);