// -----------------------------------------------------------------------------------////	Lightbox Slideshow v1.1//	by Justin Barkhuff - http://www.justinbarkhuff.com/lab/lightbox_slideshow///  Updated: 2007-08-15////	Largely based on Lightbox v2.02//	by Lokesh Dhakar - http://huddletogether.com/projects/lightbox2///	3/31/06////	Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/////	The code inserts html at the bottom of the page that looks similar to this:////	<div id="overlay"></div>//	<div id="lightbox">//		<div id="outerImageContainer">//			<div id="imageContainer">//				<img id="lightboxImage" />//				<div id="hoverNav">//					<a href="javascript:void(0);" id="prevLinkImg">&laquo; prev</a>//					<a href="javascript:void(0);" id="nextLinkImg">next &raquo;</a>//				</div>//				<div id="loading">//					<a href="javascript:void(0);" id="loadingLink">loading</a>//				</div>//			</div>//		</div>//		<div id="imageDataContainer">//			<div id="imageData">//				<div id="imageDetails">//					<span id="caption"></span>//					<span id="numberDisplay"></span>//					<span id="detailsNav">//						<a id="prevLinkDetails" href="javascript:void(0);">&laquo; prev</a>//						<a id="nextLinkDetails" href="javascript:void(0);">next &raquo;</a>//						<a id="slideShowControl" href="javascript:void(0);">stop slideshow</a>//					</span>//				</div>//				<div id="close">//					<a id="closeLink" href="javascript:void(0);">close</a>//				</div>//			</div>//		</div>//	</div>//// -----------------------------------------------------------------------------------////	Lightbox Object//var Lightbox = {		activeImage : null,	badObjects : ['select','object','embed'],	container : null,	enableSlideshow : null,	groupName : null,	imageArray : [],	options : null,	overlayDuration : null,	overlayOpacity : null,	playSlides : null,	refTags : ['a','area'],	relAttribute : null,	resizeDuration : null,	slideShowTimer : null,	startImage : null,		//	// initialize()	// Constructor sets class properties and configuration options and	// inserts html at the bottom of the page which is used to display the shadow 	// overlay and the image container.	//	initialize: function(options) {		if (!document.getElementsByTagName){ return; }				this.options = $H({			animate : false, // resizing animations			autoPlay : true, // should slideshow start automatically			borderSize : 10, // if you adjust the padding in the CSS, you will need to update this variable			containerID : document, // lightbox container object			enableSlideshow : true, // enable slideshow feature			googleAnalytics : false, // track individual image views using Google Analytics			imageDataLocation : 'south', // location of image caption information			initImage : '', // ID of image link to automatically launch when upon script initialization			loop : true, // whether to continuously loop slideshow images			overlayDuration : .2, // time to fade in shadow overlay			overlayOpacity : .8, // transparency of shadow overlay			prefix : '', // ID prefix for all dynamically created html elements			relAttribute : 'lightbox', // specifies the rel attribute value that triggers lightbox			resizeSpeed : 4, // controls the speed of the image resizing (1=slowest and 10=fastest)			showGroupName : false, // show group name of images in image details			slideTime : 4, // time to display images during slideshow			strings : { // allows for localization				closeLink : 'close',				loadingMsg : 'loading',				nextLink : 'next &raquo;',				prevLink : '&laquo; prev',				startSlideshow : 'start slideshow',				stopSlideshow : 'stop slideshow',				numDisplayPrefix : 'Image',				numDisplaySeparator : 'of'			}        }).merge(options);				if(this.options.animate){			this.overlayDuration = Math.max(this.options.overlayDuration,0);			this.options.resizeSpeed = Math.max(Math.min(this.options.resizeSpeed,10),1);			this.resizeDuration = (11 - this.options.resizeSpeed) * 0.15;		}else{			this.overlayDuration = 0;			this.resizeDuration = 0;		}				this.enableSlideshow = this.options.enableSlideshow;		this.overlayOpacity = Math.max(Math.min(this.options.overlayOpacity,1),0);		this.playSlides = this.options.autoPlay;		this.container = $(this.options.containerID);		this.relAttribute = this.options.relAttribute;		this.updateImageList();				var objBody = this.container != document ? this.container : document.getElementsByTagName('body').item(0);				var objOverlay = document.createElement('div');		objOverlay.setAttribute('id',this.getID('overlay'));		objOverlay.style.display = 'none';		objBody.appendChild(objOverlay);		Event.observe(objOverlay,'click',this.end.bindAsEventListener(this));				var objLightbox = document.createElement('div');		objLightbox.setAttribute('id',this.getID('lightbox'));		objLightbox.style.display = 'none';		objBody.appendChild(objLightbox);				var objImageDataContainer = document.createElement('div');		objImageDataContainer.setAttribute('id',this.getID('imageDataContainer'));		objImageDataContainer.className = this.getID('clearfix');		var objImageData = document.createElement('div');		objImageData.setAttribute('id',this.getID('imageData'));		objImageDataContainer.appendChild(objImageData);			var objImageDetails = document.createElement('div');		objImageDetails.setAttribute('id',this.getID('imageDetails'));		objImageData.appendChild(objImageDetails);			var objCaption = document.createElement('span');		objCaption.setAttribute('id',this.getID('caption'));		objImageDetails.appendChild(objCaption);			var objNumberDisplay = document.createElement('span');		objNumberDisplay.setAttribute('id',this.getID('numberDisplay'));		objImageDetails.appendChild(objNumberDisplay);		var objDetailsNav = document.createElement('span');		objDetailsNav.setAttribute('id',this.getID('detailsNav'));		objImageDetails.appendChild(objDetailsNav);		var objPrevLink = document.createElement('a');		objPrevLink.setAttribute('id',this.getID('prevLinkDetails'));		objPrevLink.setAttribute('href','javascript:void(0);');		objPrevLink.innerHTML = this.options.strings.prevLink;		objDetailsNav.appendChild(objPrevLink);		Event.observe(objPrevLink,'click',this.showPrev.bindAsEventListener(this));				var objNextLink = document.createElement('a');		objNextLink.setAttribute('id',this.getID('nextLinkDetails'));		objNextLink.setAttribute('href','javascript:void(0);');		objNextLink.innerHTML = this.options.strings.nextLink;		objDetailsNav.appendChild(objNextLink);		Event.observe(objNextLink,'click',this.showNext.bindAsEventListener(this));		var objSlideShowControl = document.createElement('a');		objSlideShowControl.setAttribute('id',this.getID('slideShowControl'));		objSlideShowControl.setAttribute('href','javascript:void(0);');		objDetailsNav.appendChild(objSlideShowControl);		Event.observe(objSlideShowControl,'click',this.toggleSlideShow.bindAsEventListener(this));		var objClose = document.createElement('div');		objClose.setAttribute('id',this.getID('close'));		objImageData.appendChild(objClose);			var objCloseLink = document.createElement('a');		objCloseLink.setAttribute('id',this.getID('closeLink'));		objCloseLink.setAttribute('href','javascript:void(0);');		objCloseLink.innerHTML = this.options.strings.closeLink;		objClose.appendChild(objCloseLink);			Event.observe(objCloseLink,'click',this.end.bindAsEventListener(this));		if(this.options.imageDataLocation == 'north'){			objLightbox.appendChild(objImageDataContainer);		}			var objOuterImageContainer = document.createElement('div');		objOuterImageContainer.setAttribute('id',this.getID('outerImageContainer'));		objLightbox.appendChild(objOuterImageContainer);		var objImageContainer = document.createElement('div');		objImageContainer.setAttribute('id',this.getID('imageContainer'));		objOuterImageContainer.appendChild(objImageContainer);			var objLightboxImage = document.createElement('img');		objLightboxImage.setAttribute('id',this.getID('lightboxImage'));		objImageContainer.appendChild(objLightboxImage);			var objHoverNav = document.createElement('div');		objHoverNav.setAttribute('id',this.getID('hoverNav'));		objImageContainer.appendChild(objHoverNav);			var objPrevLinkImg = document.createElement('a');		objPrevLinkImg.setAttribute('id',this.getID('prevLinkImg'));		objPrevLinkImg.setAttribute('href','javascript:void(0);');		objHoverNav.appendChild(objPrevLinkImg);		Event.observe(objPrevLinkImg,'click',this.showPrev.bindAsEventListener(this));				var objNextLinkImg = document.createElement('a');		objNextLinkImg.setAttribute('id',this.getID('nextLinkImg'));		objNextLinkImg.setAttribute('href','javascript:void(0);');		objHoverNav.appendChild(objNextLinkImg);		Event.observe(objNextLinkImg,'click',this.showNext.bindAsEventListener(this));			var objLoading = document.createElement('div');		objLoading.setAttribute('id',this.getID('loading'));		objImageContainer.appendChild(objLoading);			var objLoadingLink = document.createElement('a');		objLoadingLink.setAttribute('id',this.getID('loadingLink'));		objLoadingLink.setAttribute('href','javascript:void(0);');		objLoadingLink.innerHTML = this.options.strings.loadingMsg;		objLoading.appendChild(objLoadingLink);		Event.observe(objLoadingLink,'click',this.end.bindAsEventListener(this));				if(this.options.imageDataLocation != 'north'){			objLightbox.appendChild(objImageDataContainer);		}				if(this.options.initImage != ''){			this.start($(this.options.initImage));		}	},		//	//	updateImageList()	//	Loops through specific tags within 'container' looking for 	// 'lightbox' references and applies onclick events to them.	//	updateImageList: function(){		var el, els, rel;		for(var i=0; i < this.refTags.length; i++){			els = this.container.getElementsByTagName(this.refTags[i]);			for(var j=0; j < els.length; j++){				el = els[j];				rel = String(el.getAttribute('rel'));				if (el.getAttribute('href') && (rel.toLowerCase().match(this.relAttribute))){					el.onclick = function(){Lightbox.start(this); return false;}				}			}		}	},			//	//	start()	//	Display overlay and lightbox. If image is part of a set, add siblings to imageArray.	//	start: function(imageLink) {			this.hideBadObjects();		// stretch overlay to fill page and fade in		var pageSize = this.getPageSize();		$(this.getID('overlay')).setStyle({height:pageSize.pageHeight+'px'});		new Effect.Appear(this.getID('overlay'), { duration: this.overlayDuration, from: 0, to: this.overlayOpacity });		this.imageArray = [];		this.groupName = null;				var rel = imageLink.getAttribute('rel');		var imageTitle = '';				// if image is NOT part of a group..		if(rel == this.relAttribute){			// add single image to imageArray			imageTitle = imageLink.getAttribute('title') ? imageLink.getAttribute('title') : '';			this.imageArray.push({'link':imageLink.getAttribute('href'), 'title':imageTitle});						this.startImage = 0;		} else {			// if image is part of a group..			var els = this.container.getElementsByTagName(imageLink.tagName);			// loop through anchors, find other images in group, and add them to imageArray			for (var i=0; i<els.length; i++){				var el = els[i];				if (el.getAttribute('href') && (el.getAttribute('rel') == rel)){					imageTitle = el.getAttribute('title') ? el.getAttribute('title') : '';					this.imageArray.push({'link':el.getAttribute('href'),'title':imageTitle});					if(el == imageLink){						this.startImage = this.imageArray.length-1;					}				}			}			// get group name			this.groupName = rel.substring(this.relAttribute.length+1,rel.length-1);		}		// calculate top offset for the lightbox and display 		var pageScroll = this.getPageScroll();		var lightboxTop = pageScroll.y + (pageSize.winHeight / 15);		$(this.getID('lightbox')).setStyle({top:lightboxTop+'px'}).show();		this.changeImage(this.startImage);	},	//	//	changeImage()	//	Hide most elements and preload image in preparation for resizing image container.	//	changeImage: function(imageNum){			this.activeImage = imageNum;		this.disableKeyboardNav();		this.pauseSlideShow();		// hide elements during transition		$(this.getID('loading')).show();		$(this.getID('lightboxImage')).hide();		$(this.getID('hoverNav')).hide();		$(this.getID('imageDataContainer')).hide();		$(this.getID('numberDisplay')).hide();		$(this.getID('detailsNav')).hide();				var imgPreloader = new Image();				// once image is preloaded, resize image container		imgPreloader.onload=function(){			$(Lightbox.getID('lightboxImage')).src = imgPreloader.src;			Lightbox.resizeImageContainer(imgPreloader.width,imgPreloader.height);		}		imgPreloader.src = this.imageArray[this.activeImage].link;				if(this.options.googleAnalytics){			urchinTracker(this.imageArray[this.activeImage].link);		}	},	//	//	resizeImageContainer()	//	resizeImageContainer: function(imgWidth,imgHeight) {		// get current height and width		var cDims = $(this.getID('outerImageContainer')).getDimensions();		// scalars based on change from old to new		var xScale = ((imgWidth  + (this.options.borderSize * 2)) / cDims.width) * 100;		var yScale = ((imgHeight  + (this.options.borderSize * 2)) / cDims.height) * 100;		// calculate size difference between new and old image, and resize if necessary		var wDiff = (cDims.width - this.options.borderSize * 2) - imgWidth;		var hDiff = (cDims.height - this.options.borderSize * 2) - imgHeight;		if(!( hDiff == 0)){ new Effect.Scale(this.getID('outerImageContainer'), yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'}); }		if(!( wDiff == 0)){ new Effect.Scale(this.getID('outerImageContainer'), xScale, {scaleY: false, delay: this.resizeDuration, duration: this.resizeDuration}); }		// if new and old image are same size and no scaling transition is necessary, 		// do a quick pause to prevent image flicker.		if((hDiff == 0) && (wDiff == 0)){			if(navigator.appVersion.indexOf('MSIE')!=-1){ this.pause(250); } else { this.pause(100);} 		}		$(this.getID('prevLinkImg')).setStyle({height:imgHeight+'px'});		$(this.getID('nextLinkImg')).setStyle({height:imgHeight+'px'});		$(this.getID('imageDataContainer')).setStyle({width:(imgWidth+(this.options.borderSize * 2))+'px'});		this.showImage();	},		//	//	showImage()	//	Display image and begin preloading neighbors.	//	showImage: function(){		$(this.getID('loading')).hide();		new Effect.Appear(this.getID('lightboxImage'), { duration: 0.5, queue: 'end', afterFinish: function(){	Lightbox.updateDetails(); } });		this.preloadNeighborImages();	},	//	//	updateDetails()	//	Display caption, image number, and bottom nav.	//	updateDetails: function() {		$(this.getID('caption')).show();		$(this.getID('caption')).update(this.imageArray[this.activeImage].title);				// if image is part of set display 'Image x of y' 		if(this.imageArray.length > 1){			var num_display = this.options.strings.numDisplayPrefix + ' ' + eval(this.activeImage + 1) + ' ' + this.options.strings.numDisplaySeparator + ' ' + this.imageArray.length;			if(this.options.showGroupName && this.groupName != ''){				num_display += ' '+this.options.strings.numDisplaySeparator+' '+this.groupName;			}			$(this.getID('numberDisplay')).update(num_display).show();			if(!this.enableSlideshow){				$(this.getID('slideShowControl')).hide();			}			$(this.getID('detailsNav')).show();		}				new Effect.Parallel(			[ new Effect.SlideDown( this.getID('imageDataContainer'), { sync: true }), 			  new Effect.Appear(this.getID('imageDataContainer'), { sync: true }) ], 			{ duration:.65, afterFinish: function() { Lightbox.updateNav();} } 		);	},		//	//	updateNav()	//	Display appropriate previous and next hover navigation.	//	updateNav: function() {		if(this.imageArray.length > 1){			$(this.getID('hoverNav')).show();			if(this.enableSlideshow){				if(this.playSlides){					this.startSlideShow();				} else {					this.stopSlideShow();				}			}		}		this.enableKeyboardNav();	},	//	//	startSlideShow()	//	Starts the slide show	//	startSlideShow: function(){		this.playSlides = true;		this.slideShowTimer = new PeriodicalExecuter(function(pe){ Lightbox.showNext(); pe.stop(); },this.options.slideTime);		$(this.getID('slideShowControl')).update(this.options.strings.stopSlideshow);	},		//	//	stopSlideShow()	//	Stops the slide show	//	stopSlideShow: function(){		this.playSlides = false;		if(this.slideShowTimer){			this.slideShowTimer.stop();		}		$(this.getID('slideShowControl')).update(this.options.strings.startSlideshow);	},	//	//	stopSlideShow()	//	Stops the slide show	//	toggleSlideShow: function(){		if(this.playSlides){			this.stopSlideShow();		}else{			this.startSlideShow();		}	},	//	//	pauseSlideShow()	//	Pauses the slide show (doesn't change the value of this.playSlides)	//	pauseSlideShow: function(){		if(this.slideShowTimer){			this.slideShowTimer.stop();		}	},		//	//	showNext()	//	Display the next image in a group	//	showNext : function(){		if(this.imageArray.length > 1){			if(!this.options.loop && ((this.activeImage == this.imageArray.length - 1 && this.startImage == 0) || (this.activeImage+1 == this.startImage))){				return this.end();			}			if(this.activeImage == this.imageArray.length - 1){				this.changeImage(0);			}else{				this.changeImage(this.activeImage+1);			}		}	},	//	//	showPrev()	//	Display the next image in a group	//	showPrev : function(){		if(this.imageArray.length > 1){			if(this.activeImage == 0){				this.changeImage(this.imageArray.length - 1);			}else{				this.changeImage(this.activeImage-1);			}		}	},		//	//	showFirst()	//	Display the first image in a group	//	showFirst : function(){		if(this.imageArray.length > 1){			this.changeImage(0);		}	},	//	//	showFirst()	//	Display the first image in a group	//	showLast : function(){		if(this.imageArray.length > 1){			this.changeImage(this.imageArray.length - 1);		}	},	//	//	enableKeyboardNav()	//	enableKeyboardNav: function() {		document.onkeydown = this.keyboardAction; 	},	//	//	disableKeyboardNav()	//	disableKeyboardNav: function() {		document.onkeydown = '';	},	//	//	keyboardAction()	//	keyboardAction: function(e) {		if (e == null) { // ie			keycode = event.keyCode;		} else { // mozilla			keycode = e.which;		}		key = String.fromCharCode(keycode).toLowerCase();				if(key == 'x' || key == 'o' || key == 'c'){ // close lightbox			Lightbox.end();		} else if(key == 'p' || key == '%'){ // display previous image			Lightbox.showPrev();		} else if(key == 'n' || key =='\''){ // display next image			Lightbox.showNext();		} else if(key == 'f'){ // display first image			Lightbox.showFirst();		} else if(key == 'l'){ // display last image			Lightbox.showLast();		} else if(key == 's'){ // toggle slideshow			if(Lightbox.imageArray.length > 0 && Lightbox.options.enableSlideshow){				Lightbox.toggleSlideShow();			}		}	},	//	//	preloadNeighborImages()	//	Preload previous and next images.	//	preloadNeighborImages: function(){		var nextImageID = this.imageArray.length - 1 == this.activeImage ? 0 : this.activeImage + 1;		nextImage = new Image();		nextImage.src = this.imageArray[nextImageID].link		var prevImageID = this.activeImage == 0 ? this.imageArray.length - 1 : this.activeImage - 1;		prevImage = new Image();		prevImage.src = this.imageArray[prevImageID].link;	},	//	//	end()	//	end: function() {		this.disableKeyboardNav();		this.pauseSlideShow();		$(this.getID('lightbox')).hide();		new Effect.Fade(this.getID('overlay'), { duration:this.overlayDuration });		this.showBadObjects();	},		//	//	showBadObjects()	//	showBadObjects: function (){		var els;		var tags = Lightbox.badObjects;		for(var i=0; i<tags.length; i++){			els = document.getElementsByTagName(tags[i]);			for(var j=0; j<els.length; j++){				$(els[j]).setStyle({visibility:'visible'});			}		}	},		//	//	hideBadObjects()	//	hideBadObjects: function (){		var els;		var tags = Lightbox.badObjects;		for(var i=0; i<tags.length; i++){			els = document.getElementsByTagName(tags[i]);			for(var j=0; j<els.length; j++){				$(els[j]).setStyle({visibility:'hidden'});			}		}	},			//	// pause(numberMillis)	// Pauses code execution for specified time. Uses busy code, not good.	// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602	//	pause: function(numberMillis) {		var now = new Date();		var exitTime = now.getTime() + numberMillis;		while(true){			now = new Date();			if (now.getTime() > exitTime)				return;		}	},	//	// getPageScroll()	// Returns array with x,y page scroll values.	// Core code from - quirksmode.org	//	getPageScroll: function(){		var x,y;		if (self.pageYOffset) {			x = self.pageXOffset;			y = self.pageYOffset;		} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict			x = document.documentElement.scrollLeft;			y = document.documentElement.scrollTop;		} else if (document.body) {// all other Explorers			x = document.body.scrollLeft;			y = document.body.scrollTop;		}		return {x:x,y:y};	},	//	// getPageSize()	// Returns array with page width, height and window width, height	// Core code from - quirksmode.org	// Edit for Firefox by pHaez	//	getPageSize: function(){		var scrollX,scrollY,windowX,windowY,pageX,pageY;		if (window.innerHeight && window.scrollMaxY) {				scrollX = document.body.scrollWidth;			scrollY = window.innerHeight + window.scrollMaxY;		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac			scrollX = document.body.scrollWidth;			scrollY = document.body.scrollHeight;		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari			scrollX = document.body.offsetWidth;			scrollY = document.body.offsetHeight;		}				if (self.innerHeight) {	// all except Explorer			windowX = self.innerWidth;			windowY = self.innerHeight;		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode			windowX = document.documentElement.clientWidth;			windowY = document.documentElement.clientHeight;		} else if (document.body) { // other Explorers			windowX = document.body.clientWidth;			windowY = document.body.clientHeight;		}					pageY = (scrollY < windowY) ? windowY : scrollY; // for small pages with total height less then height of the viewport		pageX = (scrollX < windowX) ? windowX : scrollX; // for small pages with total width less then width of the viewport			return {pageWidth:pageX,pageHeight:pageY,winWidth:windowX,winHeight:windowY};	},	//	// getID()	// Returns formatted Lightbox element ID	//	getID: function(id){		return this.options.prefix+id;	}}// -----------------------------------------------------------------------------------Event.observe(window,'load',function(){ Lightbox.initialize(); });