	var needsCache = false;
	var cacheBackwards = false;

	$(document).ready(function(){

		//handlers to page forward and backward through thumbnails
			$("#nextThumbButton").click(function(){
				if(waiting)
					return false;
				waiting = true;
				flipForward();

				needsCache = true;
				cacheBackwards = false;

				selectImage(firstThumb);
				return false;
			});

			$("#prevThumbButton").click(function(){
				if(waiting)
					return false;
				waiting = true;
				flipBackward();

				needsCache = true;
				cacheBackwards = true;

				selectImage(firstThumb);
				return false;
			});

		//set handlers to flip images forward and backwards
			$("#prevImageButton").click(function(){
				previousImage();
				return false;
			});

			$("#nextImageButton").click(function(){
				nextImage();
				return false;
			});

		//set handler to open and close the email overlay
			$("#emailImageButton").click(function(){
				$("#emailOverlay").fadeIn("fast");
			});

			$("#emailCloseButton").click(function(){
				hideEmailOverlay();
			});

		//handlers for the rating system
			$("#rating").mousemove(function(e){
				updateRating(e);
			});

			$("#rating").click(function(){
				saveCurrentRating();
			});

		//handlers for the photo gallery display
			$("#showGalleryMenuButton").click(function(){
				switchMenuSport(Sports[currentImage]);
				$("#galleryMenu").slideDown("fast");
				return false;
			});
			$("#hideGalleryMenuButton").click(function(){
				$("#galleryMenu").fadeOut("fast");
			});

			$("#galleryMenu ul.menu li").click(function(){
				switchMenuSport($(this).attr("id"));
			});

			$("#teamLink").click(function(){
				if(TeamIDs[currentImage]){
					document.redirectForm.newTeamID.value = TeamIDs[currentImage];
					document.redirectForm.submit();
				}
			});

			$("#sportLink").click(function(){
				if(Sports[currentImage]){
					document.redirectForm.newSport.value = Sports[currentImage];
					document.redirectForm.submit();
				}
			});

		if(lastIndex == "-1"){
			$("#imageTitle").html("Sorry, this gallery is empty");
			$("#showGalleryMenuButton").click();
			return false;
		}


		//fill in the total for the '1 of 50' display
			$("#totalImageNumber").html(lastIndex + 1);

		//insert some dummy images so that
		//we always have an even multiple of thumbPageCount
		lastIndex = fillExtraSlots(lastIndex);

		//fill in the visible thumbnails
		setCurrent();

		//fill in the thumbnails on either side
		setPrevNext();

		//get the current large image
		needsCache = true;
		cacheBackwards = false;

		selectImage(0);

	});

	//page forward in the thumbnails
	function flipForward(){
		var newPos = "-" + (thumbPageWidth + 50) + "px";
		$("div.prevThumbSet").removeClass().addClass("tmp");
		$("div.currentThumbSet").animate({left:newPos.valueOf()},300).removeClass().addClass("prevThumbSet");
		$("div.nextThumbSet").animate({left:"0"},300).removeClass().addClass("currentThumbSet");
		var newPos = (thumbPageWidth + 50) + "px";
		$("div.tmp").css("left",newPos.valueOf()).removeClass().addClass("nextThumbSet");
		firstThumb = validIndex(firstThumb + thumbPageCount);
		setPrevNext();
	}

	//page backward in the thumbnails
	function flipBackward(){
		var newPos = (thumbPageWidth + 50) + "px";
		$("div.nextThumbSet").removeClass().addClass("tmp");
		$("div.currentThumbSet").animate({left: newPos.valueOf()},300).removeClass().addClass("nextThumbSet");
		$("div.prevThumbSet").animate({left:"0"},300).removeClass().addClass("currentThumbSet");
		newPos = "-" + newPos;
		$("div.tmp").css("left",newPos.valueOf()).removeClass().addClass("prevThumbSet");
		firstThumb = validIndex(firstThumb - thumbPageCount);
		setPrevNext();
	}

	function imageFileName(index){
		var imageFile = new String(Photos[index].toLowerCase());
		if(fullsizeImage)
			imageFile = imageFile.replace(".jpg","_O.jpg");
		return imageFile;
	}

	//select and display a particular image in the main pic
	//the thumbnails should already be set up so that the
	//current image's thumbnail is in the visible set
	function selectImage(newImageIndex){
		waiting = true;
		$("img.thumb_" + currentImage).removeClass("current");
		$("#imageTitle").html(Titles[newImageIndex]);
		$("#imageHeader").html(Headers[newImageIndex]);
		//$("#mainPic").attr("title",Titles[newImageIndex]);
		$("#mainPic").attr("alt",Titles[newImageIndex]);
		$("img.thumb_" + newImageIndex).addClass("current");
		hideEmailOverlay();
		$("#hideGalleryMenuButton").click();
		switchMainImage(imageFileName(newImageIndex));
		currentImage = newImageIndex;
		$("#currentImageNumber").html(currentImage + 1);
		updateRelatedLinks();
	}

	function switchMainImage(newSource){
		$("#mainPic").fadeOut("fast",function(){
			$("#mainPic").loadImage(newSource,function(){
				startCache();
				$("#mainPic").attr("src",newSource).fadeIn("fast",function(){
					waiting = false;
				});
			});
		});
	}

	function startCache(){
		if(needsCache)
			cacheImages(firstThumb,cacheBackwards);
		needsCache = false;
		cacheBackwards = false;
	}


	//load an image
	$.fn.loadImage = function(src, f){
		return this.each(function(){
			var i = new Image();
			i.onload = f;
			i.src = src;
		});
	}


	//get the next image as the main pic
	function nextImage(){
		var newImage = currentImage + 1;
		if(CIDs[newImage] == "0")
			newImage = 0;

		if(newImage % thumbPageCount == 0){
			flipForward();
			needsCache = true;
			cacheBackwards = false;
			selectImage(newImage);
		}else{
			selectImage(newImage);
		}
	}

	//select the previous image as the main pic
	function previousImage(){
		var newImage = validIndex(currentImage - 1);
		while(CIDs[newImage] == "0")
			newImage--;

		if(currentImage % thumbPageCount == 0){
			flipBackward();

			needsCache = true;
			cacheBackwards = true;
			selectImage(newImage);
		}else{
			selectImage(newImage);
		}
	}

	//sets a single thumbnail ($image points to the img element)
	//using the Photos,Titles,etc. arrays, and the given index therein
	function setupThumbnail($image,index){
		$image.attr("src",Photos[index].toLowerCase().replace(".jpg","_TN.jpg"));
		//$image.attr("title",Titles[index]);
		$image.attr("alt",Titles[index]);
		if(CIDs[index] == "0"){
			$image.removeClass().addClass("empty");
			$image.unbind("click");
		}else{
			$image.removeClass().addClass("thumb_" + index);
			$image.unbind("click").click(function(){selectImage(index)});
		}
	}

	//sets up the visible thumbnails...
	//this only needs to be done once, because after that
	//they come from either side, and are set up by setPrevNext
	function setCurrent(){
		//set up the positions an sizes of the thumbnail boxes
		var boxHeight = new String(thumbPageHeight + "px");
		var boxWidth = new String(thumbPageWidth + "px");
		$("#thumbContainer").css("height",boxHeight.valueOf());
		$("#thumbContainer").css("width",boxWidth.valueOf());
		$("#thumbContainer div").css("height",boxHeight.valueOf());
		$("#thumbContainer div").css("width",boxWidth.valueOf());
		$("div.currentThumbSet").css({left:0});
		$("div.nextThumbSet").css("left",(thumbPageWidth + 50) + "px");
		$("div.prevThumbSet").css("left","-" + (thumbPageWidth + 50) + "px");

		var $images = $("div.currentThumbSet img");
		var len = $images.length;
		for(var k=0; k < len; k++){
			var thisIndex = validIndex(firstThumb + k);
			var $theImageTag = $images.eq(k);
			setupThumbnail($theImageTag,thisIndex);
		}
	}

	//set up the pages of thumbnails
	//to either side of the visible set
	function setPrevNext(){
		var $images = $("div.nextThumbSet img");
		var len = $images.length;
		for(var k=0; k < len; k++){
			var thisIndex = validIndex(firstThumb + k + thumbPageCount);
			var $theImageTag = $images.eq(k);
			setupThumbnail($theImageTag,thisIndex);
		}
		$images = $("div.prevThumbSet img");
		len = $images.length;
		for(var k = 0; k < len; k++){
			var thisIndex = validIndex(firstThumb + k - thumbPageCount);
			var $theImageTag = $images.eq(k);
			setupThumbnail($theImageTag,thisIndex);
		}

	}

	//handle wrapping forward and backward by
	//adjusting the array index to point to
	//a valid element of Photos,Titles, etc.
	function validIndex(uncleanIndex){
		if(uncleanIndex < 0){
			return (lastIndex + 1 + uncleanIndex);
		}else{
			return uncleanIndex % (lastIndex + 1);
		}
	}

	//put in dummy images so that all thumb pages are full
	function fillExtraSlots(lastRealIndex){
		while(lastRealIndex % thumbPageCount != (thumbPageCount - 1)){
			lastRealIndex++;
			CIDs[lastRealIndex]="0";
			Photos[lastRealIndex] = "/sitegraphics/spacer.gif";
			Titles[lastRealIndex]="";
			Headers[lastRealIndex]="";
		}
		return lastRealIndex;
	}

	//change the gallery menu to show the correct tab
	function switchMenuSport(newSport){
		var theSport;
		switch(newSport){
			case "Bowling":
			case "Dodgeball":
			case "Flag_Football":
			case "Kickball":
			case "Softball":
			case "Volleyball":
			case "Mini_Golf":
			case "Events":
			case "Other":
				theSport = newSport;
				break;
			default:
				theSport = "Events";
				break;
		}

		$("#galleryMenu div").css("display","none");
		$("#galleryMenu div#" + theSport + "_galleries").css("display","block");
		$("#galleryMenu ul.menu li").removeClass();
		$("#galleryMenu ul.menu li#" + theSport).addClass("current");

	}


	function updateRelatedLinks(){
		if(TeamIDs[currentImage]){
			$("#teamLink").css("display","block");
		}else{
			$("#teamLink").css("display","none");
		}
		if(Sports[currentImage]){
			$("#sportLink").css("display","block");
			$("#sportLink span").html(Sports[currentImage]);
		}else{
			$("#sportLink").css("display","none");
		}

	}

	/*
			//cache large images that can be selected with one click
			function cacheImages(firstThumbIndex,backwards){
				if(backwards){
					for(var k = 0; k < thumbPageCount; k++){
						imageCache[k] = new Image();
						imageCache[k].src = imageFileName(validIndex(firstThumbIndex + thumbPageCount - 2 - k));
					}
					imageCache[thumbPageCount] = new Image();
					imageCache[thumbPageCount].src = imageFileName(validIndex(firstThumbIndex - thumbPageCount));
				}else{
					for(var k = 0; k < thumbPageCount; k++){
						imageCache[k] = new Image();
						imageCache[k].src = imageFileName(validIndex(firstThumbIndex + k + 1));
					}
					imageCache[thumbPageCount] = new Image();
					imageCache[thumbPageCount].src = imageFileName(validIndex(firstThumbIndex - thumbPageCount));

					imageCache[thumbPageCount + 1] = new Image();
					imageCache[thumbPageCount + 1].src = imageFileName(validIndex(firstThumbIndex - 1));

				}
			}

	*/

	//set up in the cacheQue array which images are to be loaded
	function cacheImages(firstThumbIndex,backwards){
		if(backwards){
			for(var k = 0; k < thumbPageCount; k++){
				cacheQue[k] = imageFileName(validIndex(firstThumbIndex + thumbPageCount - 2 - k));
			}
			cacheQue[thumbPageCount] = imageFileName(validIndex(firstThumbIndex - thumbPageCount));
			cacheQue[thumbPageCount + 1] = "";
		}else{
			for(var k = 0; k < thumbPageCount; k++){
				cacheQue[k]= imageFileName(validIndex(firstThumbIndex + k + 1));
			}
			cacheQue[thumbPageCount] = imageFileName(validIndex(firstThumbIndex - thumbPageCount));
			cacheQue[thumbPageCount + 1] = imageFileName(validIndex(firstThumbIndex - 1));
		}
		cacheFromQue(0);
	}

	//use the cache que to preload the desired images
	function cacheFromQue(queIndex){
		if(queIndex > thumbPageCount + 1 || cacheQue[queIndex] == ""){
			return false;
		}

		imageCache[queIndex] = new Image;
		imageCache[queIndex].onload = function(){cacheFromQue(queIndex + 1);};
		imageCache[queIndex].src = cacheQue[queIndex];
	}


	//create the ajax call that actually sends the image email
	function emailCurrentPhoto(){
		var toEmail = $("#toEmail").attr("value");
		var fromEmail = $("#fromEmail").attr("value");
		var emailMessage = $("#emailMessage").attr("value")
		if(toEmail == "" || fromEmail == ""){
			alert("Please enter two valid email addresses.");
			return false;
		}

		if(!validEmail(toEmail) || !validEmail(fromEmail)){
			alert("Please enter two valid email addresses.");
			return false;
		}
		$("#photoMessage").html("sending email...");
		$("#photoMessage").fadeIn("slow");

		$("#toEmail").attr("value","");

		$.post(
			"/shared/gallery_email.asp",
			"to="+escape(toEmail)+"&from="+escape(fromEmail)+"&message="+escape(emailMessage)+"&cid="+CIDs[currentImage],
			function (responseData,statusText){$("#photoMessage").html(responseData);}
		);

	}

	//validate an email address using regExp
	function validEmail(emailString) {
		 var emailReg = "^[\\w-_\.]*[\\w-_\.]\@[\\w]\.+[\\w]+[\\w]$";
		 var regex = new RegExp(emailReg);
		 return regex.test(emailString);
	}

	//hide the email overlay
	function hideEmailOverlay(){
		if($("#emailOverlay").css("display") != "none"){
			$("#emailOverlay").fadeOut("fast");
			$("#toEmail").attr("value","");
			$("#emailMessage").attr("value","");
			$("#photoMessage").hide("fast");
		}
	}

	/*
	//when the mouse is floating over the rating widget,
	//we keep track of the rating that is under the mouse
	function updateRating(e){
		currentRating = Math.floor(parseInt(e.clientX) / (cssToNumber($("#rating").css("width")) / 4)) + 1;
		//also adjust the background image to show the selected rating!!!
	}

	//when the user clicks on the rating widget, we
	//lock-in that particular rating.
	//NOTE: we don't detect the rating here b/c it's
	//constantly updated by updateRating
	function saveCurrentRating(){
		alert(currentRating);
		//do an ajax call to save the rating
	}

	//translate something like 120px to just 120.
	function cssToNumber(pixels){
		var numStr = "";
		var str = new String(pixels);
		for(var k = 0; k < str.length; k++){
			if(!isNaN(parseInt(str.charAt(k)))){
				numStr = numStr + str.charAt(k);
			}else{
				break;
			}
		}
		return parseInt(numStr);
	}
	*/
