/*
    This file is part of JonDesign's SmoothGallery v2.0.

    JonDesign's SmoothGallery is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    JonDesign's SmoothGallery is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with JonDesign's SmoothGallery; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Main Developer: Jonathan Schemoul (JonDesign: http://www.jondesign.net/)
    Contributed code by:
    - Christian Ehret (bugfix)
	- Nitrix (bugfix)
	- Valerio from Mad4Milk for his great help with the carousel scrolling and many other things.
	- Archie Cowan for helping me find a bugfix on carousel inner width problem.
	- Tomocchino from #mootools for the preloader class
	Many thanks to:
	- The mootools team for the great mootools lib, and it's help and support throughout the project.
*/

var SmoothGallery = {
	version: '2.0'
};

/* Main Part of the Gallery Script */
// declaring the class
//var gallery = {
var gallery = new Class({
	Implements: [Events, Options],
	options: {
		showArrows: true,
		showCarousel: true,
		
		showNumberCount: false,
		showInfopane: false,
		showDebug: false, /* show debug set to false */
		
		embedLinks: true,
		embedMediaLinks: true,
		fadeDuration: 500,
		timed: false,
		delay: 9000,
		preloader: true,
		preloaderImage: true,
		preloaderErrorImage: true,
		/* Data retrieval */
		manualData: [],
		populateFrom: false,
		populateData: true,
		destroyAfterPopulate: true,
		elementSelector: "div.imageElement",
		titleSelector: "h3",
		subtitleSelector: "p",
		linkSelector: "a.open",
		linkMediaSelector: "a.open_media",
		
		//imageSelector: "img.full",
		//thumbnailSelector: "img.thumbnail",
		imageSelector: "a.full",
		thumbnailSelector: "a.thumbnail",
		
		thumbnailMediaSelector: "a.thumbnailMedia",
		
		/* Transition */
		defaultTransition: "fade",
		randomTransition: false,
		dataTransition: ['crossfade', 'fade', 'fadebg', 'continuousvertical', 'continuoushorizontal', 'fadeslideleft', 'overlayverticalfade'],
		
		/* InfoPane options */
		slideInfoZoneOpacity: 0.8, // 0.7
		slideInfoZoneSlide: true,
		/* Carousel options */
		carouselMinimizedOpacity: 0.4,
		carouselMinimizedHeight: 20,
		carouselMaximizedOpacity: 0.8, // 0.9
		
		/* Display timer options */
		showDisplayTimer: false,
		
		thumbWidth: 54,
		thumbHeight: 40,
		
		thumbSpacing: 10,
		thumbIdleOpacity: 0.2,
		textShowCarousel: 'Thumbnails',
		showCarouselLabel: true,
		thumbCloseCarousel: true,
		useThumbGenerator: false,
		
		thumbGenerator: base_url + 'scripts/image_resizer.php', // base_url var is defined in misc.js
		
		useExternalCarousel: false,
		carouselElement: false,
		carouselHorizontal: true,
		activateCarouselScroller: true,
		carouselPreloader: true,
		textPreloadingCarousel: 'Loading...',
		/* CSS Classes */
		baseClass: 'jdGallery',
		withArrowsClass: 'withArrows',
		/* Plugins: HistoryManager */
		useHistoryManager: false,
		customHistoryKey: false,
		// flag default image
		defaultImage: false,
		// randomize image order onload
		random: true
	},
	initialize: function(element, options) {
		this.setOptions(options);
		this.fireEvent('onInit');
		this.currentIter = 0;
		this.lastIter = 0;
		this.maxIter = 0;
		this.galleryElement = element;
		this.galleryData = this.options.manualData;
		this.galleryInit = 1;
		this.galleryElements = Array();
		this.thumbnailElements = Array();
		this.galleryElement.addClass(this.options.baseClass);
		
		this.populateFrom = element;
		if (this.options.populateFrom)
			this.populateFrom = this.options.populateFrom;		
		if (this.options.populateData)
			this.populateData();
		element.style.display = "block";
		
		if (this.options.useHistoryManager)
			this.initHistory();
		
		if (this.options.embedLinks) {
			this.currentLink = new Element('a').addClass('open').setProperties({
				href: 'javascript:void(0); ',
				title: ''
			}).injectInside(element);
			if ((!this.options.showArrows) && (!this.options.showCarousel))
				this.galleryElement = element = this.currentLink;
			else
				this.currentLink.setStyle('display', 'none');
		}
		
		this.constructElements();
		if ((this.galleryData.length>1)&&(this.options.showArrows)) {
			var leftArrow = new Element('a').addClass('left').addEvent(
				'click',
				this.prevItem.bind(this)
			).injectInside(element);
			var rightArrow = new Element('a').addClass('right').addEvent(
				'click',
				this.nextItem.bind(this)
			).injectInside(element);
			this.galleryElement.addClass(this.options.withArrowsClass);
		}
		this.loadingElement = new Element('div').addClass('loadingElement').injectInside(element);
		this.loadingElementText = new Element('div').setProperty('id', 'loadingText').setHTML(this.options.textPreloadingCarousel).injectInside(this.loadingElement);
		if (this.options.showInfopane) this.initInfoSlideshow();
		if (this.options.showCarousel) this.initCarousel();
		this.doSlideShow(1);			
	},
	populateData: function() {
		currentArrayPlace = this.galleryData.length;
		options = this.options;
		var data = $A(this.galleryData);
		data.extend(this.populateGallery(this.populateFrom, currentArrayPlace));
		this.galleryData = data;
		this.fireEvent('onPopulated');
	},
	populateGallery: function(element, startNumber) {
		var data = [];
		options = this.options;
		currentArrayPlace = startNumber;
		var x = this.getTransition;
		element.getElements(options.elementSelector).each(function(el) {
			elementDict = {
				//image: el.getElement(options.imageSelector).getProperty('src'),
				image: el.getElement(options.imageSelector).getProperty('href'),
				number: currentArrayPlace,
				transition: x() //this.options.defaultTransition
			};
			elementDict.extend = $extend;
			////////////////////////
			// add by Lesly 07/22/08
			if (options.defaultImage)
				elementDict.extend({
					imageId: el.getElement(options.imageSelector).getProperty('id')
				});
			////////////////////////
			if ((options.showInfopane) | (options.showCarousel))
				elementDict.extend({
					title: el.getElement(options.titleSelector).innerHTML,
					description: el.getElement(options.subtitleSelector).innerHTML
				});
			if (options.embedLinks)
				elementDict.extend({
					link: el.getElement(options.linkSelector).href || false,
					linkTitle: el.getElement(options.linkSelector).title || false,
					linkTarget: el.getElement(options.linkSelector).getProperty('target') || false
				});
			if ((!options.useThumbGenerator) && (options.showCarousel))
				elementDict.extend({
					//thumbnail: el.getElement(options.thumbnailSelector).getProperty('src') || false,
					thumbnail: el.getElement(options.thumbnailSelector).getProperty('href') || false,
					thumbnailMedia: el.getElement(options.thumbnailMediaSelector).getProperty('href') || false
				});
			else if (options.useThumbGenerator) {		
				// match a(ny) URI, the variable "domain" is defined in misc.js
				var match = new RegExp('http(s)?:\/\/(' + domain + '\/)?(.*)');	// ('/http(s)?:\/\/(' + domain + '\/)?(.*)/')		
				// remove http:// that ie sticks on the front of the variable
				var imgPath = elementDict.image.replace(match, "$3"); 				
				// var imgPath = '../../' + imgPath;
				var imgPath = '../' + imgPath;
				// if(_access)window.alert(imgPath);				
				elementDict.extend({
					thumbnail: options.thumbGenerator + '?imgfile=' + imgPath + '&max_width=' + options.thumbWidth + '&max_height=' + options.thumbHeight, 
					thumbnailMedia: el.getElement(options.thumbnailMediaSelector).getProperty('href') || false
				});			
			}
			data.extend([elementDict]);
			currentArrayPlace++;
			if (this.options.destroyAfterPopulate)
				el.remove();
		});
		return data;
	},
	constructElements: function() {
		el = this.galleryElement;
		this.maxIter = this.galleryData.length;
		var currentImg;
		for(i=0; i<this.galleryData.length; i++) {
			var currentImg = new Fx.Styles(
				new Element('div').addClass('slideElement').setStyles({
					'position':'absolute',
					'left':'0px',
					'right':'0px',
					'margin':'0px',
					'padding':'0px',
					'backgroundPosition':"center center",
					'opacity':'0'
				}).injectInside(el),
				'opacity',
				{duration: this.options.fadeDuration}
			);
			if (this.options.preloader) {
				currentImg.source = this.galleryData[i].image;
				currentImg.loaded = false;
				currentImg.load = function(imageStyle) {					
					if (!imageStyle.loaded)	{						
						new Asset.image(imageStyle.source, {
							'onload' : function(img){								
								img.element.setStyle('backgroundImage', "url('" + img.source + "')");
								img.loaded = true;
								//if(_access)alert(currentImg.tagName);
							}.bind(this, imageStyle)
						});					
						//"url('" + base_url + '/' + image.source + "')");
					}				
				}.pass(currentImg, this);
			} else {
				currentImg.element.setStyle('backgroundImage', "url('" + this.galleryData[i].image + "')");
			}
			this.galleryElements[parseInt(i)] = currentImg;
		}
	},
	destroySlideShow: function(element) {
		var myClassName = element.className;
		var newElement = new Element('div').addClass('myClassName');
		element.parentNode.replaceChild(newElement, element);
	},
	startSlideShow: function() {
		this.fireEvent('onStart');
		this.loadingElement.style.display = "none";
		this.lastIter = this.maxIter - 1;		
		this.currentIter = ( (this.options.random) ? ($random(0, this.lastIter)) : (0) );
		
		//if(this.galleryData[i].imageId == 174)
		//	alert(this.galleryData[i].imageId);
			
		this.galleryInit = 0;
		
		this.goTo(parseInt(this.currentIter)); // added 11-23-07 for random number
		this.startDisplayTimer(); // initiate display timer
		
		// apply transition to reveal image
		gallery.Transitions[this.galleryData[parseInt(this.currentIter)].transition].pass([
			this.galleryElements[0],
			this.galleryElements[parseInt(this.currentIter)],
			0,
			parseInt(this.currentIter)], this)(); 
		//this.galleryElements[parseInt(this.currentIter)].set({opacity: 1});
		//this.galleryElements[parseInt(this.currentIter)].start({opacity: 1});
		
		if (this.options.showInfopane)
			//this.showInfoSlideShow.delay(1000, this);
			//this.showInfoSlideShow.delay((1000 + this.options.fadeDuration), this);
			
		var textShowCarousel = formatString(this.options.textShowCarousel, this.currentIter + 1, this.maxIter);
		if (this.options.showCarousel && (!this.options.carouselPreloader))
			this.carouselBtn.setHTML(textShowCarousel).setProperty('title', textShowCarousel);
		//this.prepareTimer();
		if (this.options.embedLinks)
			//this.makeLink(this.currentIter);
		this.showcount(); // show count with title in show pane	
		this.debug(this.galleryData[i]); // show debug, if debug mode is set to true
	},
	nextItem: function() {
		this.fireEvent('onNextCalled');
		this.nextIter = this.currentIter + 1;
		if (this.nextIter >= this.maxIter)
			this.nextIter = 0;
		this.galleryInit = 0;
		this.goTo(this.nextIter);
	},
	prevItem: function() {
		this.fireEvent('onPreviousCalled');
		this.nextIter = this.currentIter - 1;
		if (this.nextIter <= -1)
			this.nextIter = this.maxIter - 1;
		this.galleryInit = 0;
		this.goTo(this.nextIter);
	},
	goTo: function(num) {
		this.clearTimer();
		if(this.options.preloader) {
			this.galleryElements[num].load();
			if (num == 0)
				this.galleryElements[this.maxIter - 1].load();
			else
				this.galleryElements[num - 1].load();
			if (num == (this.maxIter - 1))
				this.galleryElements[0].load();
			else
				this.galleryElements[num + 1].load();				
		}
		if (this.options.embedLinks)
			this.clearLink();
		if (this.options.showInfopane) {
			this.slideInfoZone.clearChain();
			this.hideInfoSlideShow().chain(this.changeItem.pass(num, this));
		} else
			this.currentChangeDelay = this.changeItem.delay(500, this, num);
		if (this.options.embedLinks)
			this.makeLink(num);
		this.prepareTimer();
		/*
		if (this.options.showCarousel)
			this.clearThumbnailsHighlights();
		*/
	},
	changeItem: function(num) {
		this.fireEvent('onStartChanging');
		this.galleryInit = 0;
		if (this.currentIter != num) {
			this.seconds = 0;
			this.clearDislayTimer();
			//if(this.seconds==0)alert(this.seconds);
			this.startDisplayTimer();
			for(i=0;i<this.maxIter;i++) {
				if ((i != this.currentIter)) this.galleryElements[i].set({opacity: 0});
			}
			gallery.Transitions[this.galleryData[num].transition].pass([
				this.galleryElements[this.currentIter],
				this.galleryElements[num],
				this.currentIter,
				num], this)();
			this.currentIter = num;
		}		
		var textShowCarousel = formatString(this.options.textShowCarousel, num+1, this.maxIter);
		if (this.options.showCarousel)
			this.carouselBtn.setHTML(textShowCarousel).setProperty('title', textShowCarousel);
		this.doSlideShow.bind(this)();		
		this.fireEvent('onChanged');		
		this.showcount(); // show count with title in show pane
		return this.seconds; 
	},
	clearTimer: function() {
		if (this.options.timed)
			$clear(this.timer);
	},
	prepareTimer: function() {
		if (this.options.timed) {
			// set timer value
			this.timer = this.nextItem.delay(this.options.delay, this);
			/*
			this.timer = this.nextItem
				.delay(this.options.delay.length ? 
					   this.options.delay[this.currentIter % this.options.delay.length] : 
					   this.options.delay, this); 
			*/
		}
	},
	startDisplayTimer: function() {
		if (this.options.timed && this.options.showDisplayTimer) {
			//if(_access){///////		
			// initiate creation of timer display
			this.createTimer();
			// set this.seconds (for display timer) to the timer delay set in the options
			this.seconds = (this.options.delay/1000);
			// show displayTimer
			if (this.canvasSupported) this.displayTimer(); 	
			//}///////////
		}
	},
	createTimer: function() {
		// create container for timer
		var timerELContainer = new Element('div')
			.setProperties({id: 'timer_container'})
			.setOpacity(this.options.slideInfoZoneOpacity)
			.setStyles({ position: 'absolute', zIndex: 60, left: 0, bottom: -1 })
			.injectInside(this.galleryElement); // ... or this.slideInfoZone.element
		// create canvas to display pie clock
		this.timerCanvas = new Canvas('timer_canvas', { width: 20, height: 20 })
			.setOpacity(0)
			.injectInside(timerELContainer);
		// canvas transistion fx
		this.timerCanvasFx = this.timerCanvas.effects({	
			duration: this.options.fadeDuration, 
			transition: Fx.Transitions.quadOut, 
			wait: false
		}).start({opacity: [0, 1]});
		// create div to display seconds
		var timerEl = new Element('span')
			.setProperties({ id: 'timer' })
			.addClass("xsmall bold white hidden") //
			.setStyles({ paddingLeft: 5 })
			.injectInside(timerELContainer);
		// Start creation of the context where the displayTimer will reside:
		// Make sure we don't execute when canvas isn't supported, 
		// then set "this.canvasSupported" to true, otherwise false
		if (this.timerCanvas.getContext) {
			// place canvas in the context, ??? not sure what context is yet :)
			this.ctx = this.timerCanvas.setProperties({id: 'ctx'}).getContext('2d'); 
			
			//this.ctx.fillStyle = 'rgb(141,138,120)'; // style the circle's fill in, hex:#8D8A78, alt. color rgb(233,231,21)
			//this.ctx.strokeStyle = 'rgb(233,231,219)'; // style the circle's stroke, hex:#E9E7DB, alt. color rgb(255,255,255)
			this.ctx.fillStyle = 'rgb(226,226,226)'; // circle's fill-in color, hex:#e2e2e2 -> rgb:rgb(226,226,226)
			this.ctx.strokeStyle = 'rgb(255,255,255)'; // circle's fill-in color, hex:#fff -> rgb:rgb(255,255,255)
			
			this.ctx.beginPath(); // begin path of circle
			this.ctx.arc(12, 8, 5.5, 0, Math.PI*2, true); // Outer circle
			this.ctx.fill(); // fill in the circle with specified color above
			this.ctx.stroke(); // draw stroke of the circle
			this.canvasSupported = true;
		} else {
			this.canvasSupported = false;
		}
	},
	displayTimer: function() {
		var display_timer = --this.seconds; // decrement timer by 1 sec.
		var x = 12; // x coordinate for circle
		var y = 8; // y coordinate for circle
		var r = 4.5; // Arc radius circle
		var seconds_to_percentage = ((this.seconds)/(this.options.delay/1000))*360; // Convert current second to the degrees of second		
		var startAngle = -(Math.PI/2); // Starting point on circle
		var endAngle = -(seconds_to_percentage*(Math.PI/180) - startAngle); // End point on circle		
		var clockwise = false; // clockwise or anticlockwise
		
		// Draw Pie Clock
		//this.ctx.fillStyle = 'rgb(0,53,95)'; // style the circle's fill in (hex: #00355f)
		this.ctx.fillStyle = 'rgb(0,95,170)'; // circle's fill-in color, hex:#005faa -> rgb:rgb(0,95,170)
		this.ctx.beginPath();
		this.ctx.moveTo(x,y);
		this.ctx.arc(x,y,r,startAngle,endAngle,clockwise);
		this.ctx.lineTo(x,y);
		this.ctx.fill();
		
		// set this.prev_next to false if this.prev_next=null or undefined
		if (this.prev_next == null || this.prev_next == 'undefined') this.prev_next = false;
		
		// update text to display incrementing seconds
		$('timer').setHTML(display_timer + ', ' + this.prev_next);
		
		// show pie clock in motion by the sec.
		if (this.seconds >= 1) 
			var curentDisplayTimer = this.displayTimer.delay(1000, this); // delay every 1 sec.
		return this.seconds; 
	},
	clearDislayTimer: function() { // remove all display timer elements and start over
		if (this.options.timed && this.options.showDisplayTimer) {
			//$('timer').remove(); // remove timer
			$('ctx').empty(); // empty contents of pie clock
			//this.timerCanvasFx.start({opacity: [1, 0]}); // change opacity from 1 to 0 w/ fx
			$('ctx').remove(); // remove context pie clock
			//(function() { $('ctx').remove(); }).delay(500); // remove context pie clock w/ a 1/2 sec. delay
		}
	},
	doSlideShow: function(position) {
		if (this.galleryInit == 1) {
			imgPreloader = new Image();
			imgPreloader.onload=function(){
				this.startSlideShow.delay(10, this);
			}.bind(this);
			imgPreloader.src = this.galleryData[0].image;
			if (this.options.preloader)
				this.galleryElements[0].load();
		} else {
			if (this.options.showInfopane) {
				if (this.options.showInfopane) {
					this.showInfoSlideShow.delay((500 + this.options.fadeDuration), this);
				} else
					if ((this.options.showCarousel)&&(this.options.activateCarouselScroller))
						this.centerCarouselOn(position);
			}
		}
	},
	createCarousel: function() {
		var carouselElement;
		if (!this.options.useExternalCarousel) {
			var carouselContainerElement = new Element('div').addClass('carouselContainer').injectInside(this.galleryElement);
			this.carouselContainer = new Fx.Styles(carouselContainerElement, {transition: Fx.Transitions.expoOut});
			this.carouselContainer.normalHeight = carouselContainerElement.offsetHeight;
			this.carouselContainer.set({'opacity': this.options.carouselMinimizedOpacity, 'top': (this.options.carouselMinimizedHeight - this.carouselContainer.normalHeight)});
			this.carouselBtn = new Element('a').addClass('carouselBtn').setProperties({
				title: this.options.textShowCarousel,
				id: 'carouselBtn'
			}).injectInside(carouselContainerElement);
			if(this.options.carouselPreloader)
				this.carouselBtn.setHTML(this.options.textPreloadingCarousel);
			else
				this.carouselBtn.setHTML(this.options.textShowCarousel);
			
			this.carouselBtn.addEvents({
				'click': function () {
					this.carouselContainer.clearTimer();
					this.toggleCarousel();
				}.bind(this)
			});
			
			this.carouselActive = false;
	
			carouselElement = new Element('div').addClass('carousel').injectInside(carouselContainerElement);
			this.carousel = new Fx.Styles(carouselElement);
		} else {
			carouselElement = $(this.options.carouselElement).addClass('jdExtCarousel');
		}
		this.carouselElement = new Fx.Styles(carouselElement, {transition: Fx.Transitions.expoOut});
		this.carouselElement.normalHeight = carouselElement.offsetHeight;
		if (this.options.showCarouselLabel)
			this.carouselLabel = new Element('p').addClass('label').injectInside(carouselElement);
		carouselWrapper = new Element('div').addClass('carouselWrapper').injectInside(carouselElement);
		this.carouselWrapper = new Fx.Styles(carouselWrapper, {transition: Fx.Transitions.expoOut});
		this.carouselWrapper.normalHeight = carouselWrapper.offsetHeight;
		this.carouselInner = new Element('div').addClass('carouselInner').injectInside(carouselWrapper);
		if (this.options.activateCarouselScroller) {
			this.carouselWrapper.scroller = new Scroller(carouselWrapper, {
				area: 100,
				velocity: 0.2
			});			
			this.carouselWrapper.elementScroller = new Fx.Scroll(carouselWrapper, {
				duration: 400,
				onStart: this.carouselWrapper.scroller.stop.bind(this.carouselWrapper.scroller),
				onComplete: this.carouselWrapper.scroller.start.bind(this.carouselWrapper.scroller)
			});
		}
	},
	fillCarousel: function() {
		this.constructThumbnails();
		
		//this.carouselInner.normalWidth = ((this.maxIter * (this.options.thumbWidth + this.options.thumbSpacing + 2)) + this.options.thumbSpacing) + "px";
		this.carouselInner.normalWidth = ((this.maxIter * (this.options.thumbWidth + this.options.thumbSpacing + 2)) - this.options.thumbSpacing + this.options.thumbWidth) + "px";
		
		this.carouselInner.style.width = this.carouselInner.normalWidth;
	},
	initCarousel: function () {
		this.createCarousel();
		this.fillCarousel();
		if (this.options.carouselPreloader)
			this.preloadThumbnails();
	},
	flushCarousel: function() {
		this.thumbnailElements.each(function(myFx) {
			myFx.element.remove();
			myFx = myFx.element = null;
		});
		this.thumbnailElements = [];
	},
	toggleCarousel: function() {
		if (this.carouselActive)
			this.hideCarousel();
		else
			this.showCarousel();
	},
	showCarousel: function () {
		this.fireEvent('onShowCarousel');
		this.carouselContainer.start({
			'opacity': this.options.carouselMaximizedOpacity,
			'top': 0
		}).chain(function() {
			this.carouselActive = true;
			this.carouselWrapper.scroller.start();
			this.fireEvent('onCarouselShown');
			this.carouselContainer.options.onComplete = null;
		}.bind(this));
	},
	hideCarousel: function () {
		this.fireEvent('onHideCarousel');
		var targetTop = this.options.carouselMinimizedHeight - this.carouselContainer.normalHeight;
		this.carouselContainer.start({
			'opacity': this.options.carouselMinimizedOpacity,
			'top': targetTop
		}).chain(function() {
			this.carouselActive = false;
			this.carouselWrapper.scroller.stop();
			this.fireEvent('onCarouselHidden');
			this.carouselContainer.options.onComplete = null;
		}.bind(this));
	},
	constructThumbnails: function () {
		element = this.carouselInner;
		for(i=0;i<this.galleryData.length;i++) {
			var currentImg = new Fx.Style(new Element ('div').addClass("thumbnail").setStyles({
				backgroundImage: "url('" + this.galleryData[i].thumbnail + "')",
				backgroundPosition: "center center",
				backgroundRepeat: 'no-repeat',
				marginLeft: this.options.thumbSpacing + "px",
				width: this.options.thumbWidth + "px",
				height: this.options.thumbHeight + "px"
			}).injectInside(element), "opacity", {duration: 200}).set(this.options.thumbIdleOpacity);
			if (this.options.embedMediaLinks) 
				this.mediaIcon(currentImg.element, this.galleryData[i].thumbnailMedia); // include mediaIcon function, to show icon on bottom right corner
			currentImg.element.addEvents({
				'mouseover': function (myself) {
					myself.clearTimer();
					myself.start(0.99);
					if (this.options.showCarouselLabel)
						$(this.carouselLabel).setHTML('<span class="number">' + (myself.relatedImage.number + 1) + "/" + this.maxIter + ":</span> " + myself.relatedImage.title);
				}.pass(currentImg, this),
				'mouseout': function (myself) {
					myself.clearTimer();
					myself.start(this.options.thumbIdleOpacity);
				}.pass(currentImg, this),
				'click': function (myself) {					
					this.goTo(myself.relatedImage.number);
					if (this.options.thumbCloseCarousel)
						this.hideCarousel();
				}.pass(currentImg, this)
			});
			
			currentImg.relatedImage = this.galleryData[i];
			this.thumbnailElements[parseInt(i)] = currentImg;
		}
	},
	log: function(value) {
		if(console.log)
			console.log(value);
	},
	preloadThumbnails: function() {
		var thumbnails = [];
		for(i=0;i<this.galleryData.length;i++) {
			thumbnails[parseInt(i)] = this.galleryData[i].thumbnail;
		}
		this.thumbnailPreloader = new Preloader();
		this.thumbnailPreloader.addEvent('onComplete', function() {
			var textShowCarousel = formatString(this.options.textShowCarousel, this.currentIter+1, this.maxIter);
			this.carouselBtn.setHTML(textShowCarousel).setProperty('title', textShowCarousel);
		}.bind(this));
		this.thumbnailPreloader.load(thumbnails);
	},
	clearThumbnailsHighlights: function() {
		for(i=0;i<this.galleryData.length;i++) {
			this.thumbnailElements[i].clearTimer();
			this.thumbnailElements[i].start(0.2);
		}
	},
	changeThumbnailsSize: function(width, height) {
		for(i=0;i<this.galleryData.length;i++) {
			this.thumbnailElements[i].clearTimer();
			this.thumbnailElements[i].element.setStyles({
				'width': width + "px",
				'height': height + "px"
			});
		}
	},
	centerCarouselOn: function(num) {
		if (!this.carouselWallMode) {
			var carouselElement = this.thumbnailElements[num];
			
			/* <from v1.0.1> */
			this.clearThumbnailsHighlights();
			carouselElement.clearTimer();
			carouselElement.custom(0.99);
		
			var position = carouselElement.element.offsetLeft + (carouselElement.element.offsetWidth / 2);
			var carouselWidth = this.carouselWrapper.element.offsetWidth;
			var carouselInnerWidth = this.carouselInner.offsetWidth;
			var diffWidth = carouselWidth / 2;
			var scrollPos = position - diffWidth;
			/* **********  IE Error was found here ********** */
			//this.carouselWrapper.elementScroller.scrollTo(scrollPos, 0);
			this.carouselWrapper.elementScroller.element.scrollTo(scrollPos, 0);
			/* **********  IE Error was found here ********** */
		}
	},
	initInfoSlideshow: function() {
		/*if (this.slideInfoZone.element)
			this.slideInfoZone.element.remove();*/
		this.slideInfoZone = new Fx.Styles(new Element('div').addClass('slideInfoZone').injectInside($(this.galleryElement))).set({'opacity':0});

		var slideInfoZoneTitle = new Element('h2').injectInside(this.slideInfoZone.element);
		var slideInfoZoneDescription = new Element('p').injectInside(this.slideInfoZone.element);
		this.slideInfoZone.normalHeight = this.slideInfoZone.element.offsetHeight;
		this.slideInfoZone.element.setStyle('opacity',0);
	},
	changeInfoSlideShow: function() {
		this.hideInfoSlideShow.delay(10, this);
		this.showInfoSlideShow.delay(500, this);
	},
	showInfoSlideShow: function() {
		this.fireEvent('onShowInfopane');
		this.slideInfoZone.clearTimer();
		element = this.slideInfoZone.element;
		
		element.getElement('h2').setHTML('<div class="titLeft">'+this.galleryData[this.currentIter].title+'</div>' + ( this.options.showNumberCount ? this.numberCount : '' ));
		//element.getElement('h2').setHTML(this.galleryData[this.currentIter].title);
		
		element.getElement('p').setHTML(this.galleryData[this.currentIter].description);
		if(this.options.slideInfoZoneSlide)
			this.slideInfoZone.start({'opacity': [0, this.options.slideInfoZoneOpacity], 'height': [0, this.slideInfoZone.normalHeight]});
		else
			this.slideInfoZone.start({'opacity': [0, this.options.slideInfoZoneOpacity]});
		if (this.options.showCarousel)
			this.slideInfoZone.chain(this.centerCarouselOn.pass(this.currentIter, this));
		if (this.options.embedMediaLinks)
			this.mediaBox(); // include mediabox function
		return this.slideInfoZone;
	},
	hideInfoSlideShow: function() {
		this.fireEvent('onHideInfopane');
		this.slideInfoZone.clearTimer();
		if(this.options.slideInfoZoneSlide)
			this.slideInfoZone.start({'opacity': 0, 'height': 0});
		else
			this.slideInfoZone.start({'opacity': 0});
		return this.slideInfoZone;
	},
	makeLink: function(num) {
		this.currentLink.setProperties({
			href: this.galleryData[num].link,
			title: this.galleryData[num].linkTitle
		});
		if (!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel)))
			this.currentLink.setStyle('display', 'block');
	},
	clearLink: function() {
		this.currentLink.setProperties({href: '', title: ''});
		if (!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel)))
			this.currentLink.setStyle('display', 'none');
	},
	/* To change the gallery data, those two functions : */
	flushGallery: function() {
		this.galleryElements.each(function(myFx) {
			myFx.element.remove();
			myFx = myFx.element = null;
		});
		this.galleryElements = [];
	},
	changeData: function(data) {
		this.galleryData = data;
		this.clearTimer();
		this.flushGallery();
		if (this.options.showCarousel) this.flushCarousel();
		this.constructElements();
		if (this.options.showCarousel) this.fillCarousel();
		if (this.options.showInfopane) this.hideInfoSlideShow();
		this.galleryInit = 1;
		this.lastIter = 0;
		this.currentIter = 0;
		this.doSlideShow(1);
	},
	/* Plugins: HistoryManager */
	initHistory: function() {
		this.fireEvent('onHistoryInit');
		this.historyKey = this.galleryElement.id + '-picture';
		if (this.options.customHistoryKey)
			this.historyKey = this.options.customHistoryKey();
		this.history = HistoryManager.register(
			this.historyKey,
			[1],
			function(values) {
				if (parseInt(values[0])-1 < this.maxIter)
					this.goTo(parseInt(values[0])-1);
			}.bind(this),
			function(values) {
				return [this.historyKey, '(', values[0], ')'].join('');
			}.bind(this),
			this.historyKey + '\\((\\d+)\\)');
		this.addEvent('onChanged', function(){
			this.history.setValue(0, this.currentIter+1);
		}.bind(this));
		this.fireEvent('onHistoryInited');
	},
	/* obtain media icon */
	mediaIcon: function(currentThumbnail, mediaGetIconImg) { 
		this.mediaIconImg = mediaGetIconImg;
		if (this.mediaIconImg) {
			// show a media icon in the right bottom corner of the thumbnail if media is avaible for this current slide
			var currentMediaIcon = new Element ('div').setStyles({
				backgroundImage: "url('" + this.mediaIconImg + "')",
				backgroundColor: "transparent",
				backgroundPosition: "right bottom",
				backgroundRepeat: 'no-repeat',
				width: this.options.thumbWidth + "px",
				height: this.options.thumbHeight + "px"
			}).injectInside(currentThumbnail);
		}
	},
	/* obtain media link */
	mediaGetLink: function(currentSlide, selector) {		
		this.mediaLink = currentSlide.getElement(selector);
		return this.mediaLink;
	},
	/* Play any flv, mpeg, quicktime, mp3 file using swf object and quicktime object */
	mediaBox: function() {
		this.mediaGetLink(this.slideInfoZone.element, this.options.linkMediaSelector); // include mediaGetLink function
		if (this.mediaLink) {
			this.mediaLink.addEvent('click', function(){	
				this.clearTimer(); // stop timer immediately to show media
				var mediaUrl = this.mediaLink.getProperty('rel');
				var mediaTitle = this.mediaLink.getProperty('title');
				Mediabox.open(mediaUrl, mediaTitle, 'mediabox[740 460]', this);
			}.bind(this));
		}
	},
	getTransition: function() {
		if ( (this.options.randomTransition == false) || (this.options.dataTransition.length == 1) ) {
			return this.options.defaultTransition;
		} else {
			var ranNum = Math.floor(Math.random()*this.options.dataTransition.length);
			return this.options.dataTransition[ranNum];
		}
  	},
	/* <from v1.0.1> */
    showcount: function() {
		if (this.options.showNumberCount) {
			this.numberCount = '<div class="titRight">' + (this.currentIter + 1) + "/" + this.maxIter + "</div>";
		}
    },	
	debug: function(img) {	
		if (this.options.showDebug && _access) {	
			// used for debugging purposes only, disable when done debugging
			/***********************************************************************************************/
			//this.populateData();
			var debub_str_1 = '<br><div><span class="bold">DEBUG_1:</span>&nbsp;' + (img.thumbnail.wordWrap(100, "<br />", true)) + "</div>";
			var debub_str_2 = '<div><span class="bold">DEBUG_2:</span>&nbsp;' + ("Example for other Debug strings".wordWrap(75, "<br />", true)) + "</div>";
			var debub_str_3 = '<div><span class="bold">DEBUG_3:</span>&nbsp;' + 'currentIter: ' + this.currentIter + "\nTimer: "+ this.timer+"</div>";
			this.numberCount = new Element('div').addClass('debug').injectInside(this.galleryElement);
			$(this.numberCount).setHTML(debub_str_1);
			/***********************************************************************************************/
		}
	}
	/* </from v1.0.1> this part written by Lesly */
});
gallery.implement(new Options, new Events);

gallery.Transitions = new Abstract ({
	fade: function(oldFx, newFx, oldPos, newPos){
		oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear;
		oldFx.options.duration = newFx.options.duration = this.options.fadeDuration;
		if (newPos > oldPos) newFx.start({opacity: 1});
		else 
		{
			newFx.set({opacity: 1});
			oldFx.start({opacity: 0});
		}
	},
	crossfade: function(oldFx, newFx, oldPos, newPos){
		oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear;
		oldFx.options.duration = newFx.options.duration = this.options.fadeDuration;
		newFx.start({opacity: 1});
		oldFx.start({opacity: 0});
	},
	fadebg: function(oldFx, newFx, oldPos, newPos){
		oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear;
		oldFx.options.duration = newFx.options.duration = this.options.fadeDuration / 2;
		oldFx.start({opacity: 0}).chain(newFx.start.pass([{opacity: 1}], newFx));
	},
	/**
	 * @author jon
	 */
	fadeslideleft: function(oldFx, newFx, oldPos, newPos){
		oldFx.options.transition = newFx.options.transition = Fx.Transitions.Cubic.easeOut;
		oldFx.options.duration = newFx.options.duration = 1500;
		if (newPos > oldPos)
		{
			newFx.start({
				left: [this.galleryElement.offsetWidth, 0],
				opacity: 1
			});
			oldFx.start({opacity: [1,0]});
		} else {
			newFx.start({opacity: [0,1]});
			oldFx.start({
				left: [0, this.galleryElement.offsetWidth],
				opacity: 0
			}).chain(function(fx){fx.set({left: 0});}.pass(oldFx));
		}
	},
	continuoushorizontal: function(oldFx, newFx, oldPos, newPos){
		oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear;
		if (
			((newPos > oldPos) || ((newPos==0) && (oldPos == (this.maxIter-1) ))) &&
			(!((newPos == (this.maxIter-1 )) && (oldPos == 0)))
		) {
			oldFx.set({opacity: 1});
			oldFx.start({
				left: [0, this.galleryElement.offsetWidth * -1]
			});
			newFx.set({opacity: 1, left: this.galleryElement.offsetWidth});
			newFx.start({
				left: [this.galleryElement.offsetWidth, 0]
			});
		} else  {
			oldFx.set({opacity: 1});
			oldFx.start({
				left: [0, this.galleryElement.offsetWidth]
			});
			newFx.set({opacity: 1, left: this.galleryElement.offsetWidth * -1});
			newFx.start({
				left: [this.galleryElement.offsetWidth * -1, 0]
			});
		}
	},
	continuousvertical: function(oldFx, newFx, oldPos, newPos){
		oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear;
		if (
			((newPos > oldPos) || ((newPos==0) && (oldPos == (this.maxIter-1) ))) &&
			(!((newPos == (this.maxIter-1 )) && (oldPos == 0)))
		) {
			oldFx.set({opacity: 1});
			oldFx.start({
				top: [0, this.galleryElement.offsetHeight * -1]
			});
			newFx.set({opacity: 1, top: this.galleryElement.offsetHeight});
			newFx.start({
				top: [this.galleryElement.offsetHeight, 0]
			});
		} else  {
			oldFx.set({opacity: 1});
			oldFx.start({
				top: [0, this.galleryElement.offsetHeight]
			});
			newFx.set({opacity: 1, top: this.galleryElement.offsetHeight * -1});
			newFx.start({
				top: [this.galleryElement.offsetHeight * -1, 0]
			});
		}
	},
	// created by Lesly (LRF) 11-24-07
	overlayverticalfade: function(oldFx, newFx, oldPos, newPos){
		oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear;
		oldFx.options.duration = newFx.options.duration = this.options.fadeDuration - 150;
		
		// define overlay transition
		var elementOverlayTransition = Fx.Transitions.Quint.easeInOut;	
		// create overlay and set styles
		var elementOverlay = new Element ('div').setStyles({
					position: "absolute",
					'visibility': "hidden",
					zIndex: "2",
					backgroundColor: "#cfccb9",
					margin: 0,
					padding: 0,
					width: this.galleryElement.offsetWidth + "px",
					height: (this.galleryElement.offsetHeight + 100) + "px"
				}).injectInside(this.galleryElement);
		// create overlay style fx (1st: overlay fade, 2nd: overlay vertical movement)
		var elementOverlayFadeFx = new Fx.Styles(elementOverlay, {duration: (this.options.fadeDuration) + 250, transition: elementOverlayTransition});
		var elementOverlayMoveFx = new Fx.Styles(elementOverlay, {duration: (this.options.fadeDuration) + 250, transition: elementOverlayTransition});
		
		if (newPos > oldPos) {
			elementOverlay.set({visibility: "visible"});
			elementOverlayFadeFx.start({opacity: [.4, 0]});
			elementOverlayMoveFx.start({top: [0, this.galleryElement.offsetHeight]});
			newFx.start({opacity: 1});
			
			//alert('If - oldFx: ' + oldFx.element.getStyle("width") + ', newFx: ' + newFx.element.getStyle("width"));
			//alert('If - oldFx: ' + elementOverlay.getStyle("width").toInt() + ', newFx: ' + elementOverlay.getStyle("width").toInt());
		} else {
			elementOverlay.set({visibility: "visible"});
			elementOverlayFadeFx.start({opacity: [.4, 0]});
			elementOverlayMoveFx.start({top: [(this.galleryElement.offsetHeight * -1), 0]});
			newFx.start({opacity: 1});
			oldFx.start({opacity: [1, 0]});
			
			//alert('Else - oldFx: ' + oldFx.element + ', newFx: ' + newFx.element);
		}
	}
});

/* All code copyright 2007 Jonathan Schemoul */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Follows: Preloader (class)
 * Simple class for preloading images with support for progress reporting
 * Copyright 2007 Tomocchino.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

var Preloader = new Class({  
	Implements: [Events, Options],
		options: {
			root        : '',
			period      : 100
		},  
		initialize: function(options){
		this.setOptions(options);
	},  
	load: function(sources) {
		this.index = 0;
		this.images = [];
		this.sources = this.temps = sources;
		this.total = this. sources.length;
		
		this.fireEvent('onStart', [this.index, this.total]);
		this.timer = this.progress.periodical(this.options.period, this);
		
		this.sources.each(function(source, index){
			this.images[index] = new Asset.image(this.options.root + source, {
				'onload'  : function(){ this.index++; if(this.images[index]) this.fireEvent('onLoad', [this.images[index], index, source]); }.bind(this),
				'onerror' : function(){ this.index++; this.fireEvent('onError', [this.images.splice(index, 1), index, source]); }.bind(this),
				'onabort' : function(){ this.index++; this.fireEvent('onError', [this.images.splice(index, 1), index, source]); }.bind(this)
			});
		}, this);
	},  
	progress: function() {
		this.fireEvent('onProgress', [Math.min(this.index, this.total), this.total]);
		if(this.index >= this.total) this.complete();
	},  
	complete: function(){
		$clear(this.timer);
		this.fireEvent('onComplete', [this.images]);
	},  
	cancel: function(){
		$clear(this.timer);
	}  
});
Preloader.implement(new Events, new Options);

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Follows: formatString (function)
 * Original name: Yahoo.Tools.printf
 * Copyright Yahoo.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

function formatString() {
	var num = arguments.length;
	var oStr = arguments[0];
	for (var i = 1; i < num; i++) {
		var pattern = "\\{" + (i-1) + "\\}"; 
		var re = new RegExp(pattern, "g");
		oStr = oStr.replace(re, arguments[i]);
	}
	return oStr; 
}

/* Gallery Set Dependant Script */
var gallerySet = gallery.extend({
	options: {
		manualSetData: [],
		gallerySelector: "div.galleryElement",
		galleryTitleSelector: "h2",
		textGallerySelector: 'FAMU-FSU COE Galleries',
		textShowGallerySelector: 'More Galleries',
		textGalleryInfo: '{0} image(s)',
		startWithSelector: true,
		/* Changing default options */
		textShowCarousel: '{0}/{1} Thumbnails',
		carouselPreloader: true		
	},
	initialize: function(element, options) {
		this.setOptions(options);
		this.gallerySet = this.options.manualSetData;
		this.addEvent('onPopulated', this.createGallerySelectorTab.bind(this));
		this.addEvent('onPopulated', this.createGallerySelector.bind(this));
		this.startWithSelectorFn = this.toggleGallerySelector.pass(true, this);
		if (this.options.startWithSelector)
			this.addEvent('onGallerySelectorCreated', this.startWithSelectorFn);
		this.parent(element, this.options);
	},
	populateData: function() {
		options = this.options;
		var data = $A(this.gallerySet);
		this.populateFrom.getElements(options.gallerySelector).each(function (galEl) {
			currentGalArrayPlace = 0;
			galleryDict = {
				title: galEl.getElement(options.galleryTitleSelector).innerHTML,
				elements: []
			};
			galleryDict.elements.extend(this.populateGallery(galEl, 0));
			data.extend([galleryDict]);
			if (this.options.destroyAfterPopulate)
				galEl.remove();
		}, this);
		this.gallerySet = data;
		
		//if (_access) alert(imagesArray[0].elements);
		//this.galleryData = imagesArray[0].elements;
		this.galleryData = data[0].elements;
		
		this.currentGallery = 0;
		this.fireEvent('onPopulated');
	},
	changeGallery: function(number) {
		if (number!=this.currentGallery) {
			this.changeData(this.gallerySet[number].elements);
			this.maxIter = this.gallerySet[number].elements.length;
			this.currentGallery = number;
			this.gallerySelectorBtn.setHTML(this.gallerySet[number].title);
			this.fireEvent('onGalleryChanged');
		}
		this.toggleGallerySelector(false);
	},
	createGallerySelectorTab: function() {
		this.gallerySelectorBtn = new Element('a').addClass('gallerySelectorBtn').setProperties({
			title: this.options.textShowGallerySelector
		}).setHTML(this.options.textShowGallerySelector).addEvent(
			'click',
			function(){ this.toggleGallerySelector(true); }.bind(this)
		).setOpacity(
			this.options.carouselMinimizedOpacity
		).injectInside(this.galleryElement);
		this.addEvent('onShowCarousel', function(){this.gallerySelectorBtn.setStyle('zIndex', 10)}.bind(this));
		this.addEvent('onCarouselHidden', function(){this.gallerySelectorBtn.setStyle('zIndex', 15)}.bind(this));
	},
	createGallerySelector: function() {
		this.gallerySelector = new Fx.Styles(
			new Element('div').addClass(
				'gallerySelector'
			).injectInside(
				this.galleryElement
			).setStyles({
				'display': 'none',
				'opacity': '0'
			})
		);
		this.gallerySelectorTitle = 
			new Element('h2').setHTML(
				this.options.textGallerySelector
			).injectInside(this.gallerySelector.element);
			
		/* **********  IE Error was found here ********** */
		//var gallerySelectorHeight = this.galleryElement.offsetHeight - 50 - 10 - 2;
		//var gallerySelectorHeight = this.galleryElement.offsetHeight + 50 + 10 + 2;
		//var gallerySelectorHeight = 250;
		if(window.ie) var gallerySelectorHeight = 250;
		else var gallerySelectorHeight = this.galleryElement.offsetHeight - 50 - 10 - 2;
		/* **********  IE Error was found here ********** */
		
		this.gallerySelectorWrapper = new Fx.Style(
			new Element('div').addClass(
				'gallerySelectorWrapper'
			).setStyle(
				'height', gallerySelectorHeight + "px"
			).injectInside(this.gallerySelector.element)
		);
		this.gallerySelectorInner =	new Element('div').addClass('gallerySelectorInner').injectInside(this.gallerySelectorWrapper.element);
		this.gallerySelectorWrapper.scroller = new Scroller(this.gallerySelectorWrapper.element, {
			area: 100,
			velocity: 0.3
		}).start();
		this.createGalleryButtons();
		this.fireEvent('onGallerySelectorCreated');
	},
	createGalleryButtons: function () {
		//var galleryButtonWidth = ((this.galleryElement.offsetWidth - 30) / 2) - 14 + "px";
		/* **********  IE Error was found here ********** */
		//var galleryButtonWidth = (this.galleryElement.width / 2) - 14 + "px";
		var galleryButtonWidth = (this.galleryElement.getStyle('width').toInt() / 2) - 27 + "px";
		/* **********  IE Error was found here ********** */
		//alert(galleryButtonWidth);
		this.gallerySet.each(function(galleryItem, index){
			var button = new Element('div').addClass('galleryButton').injectInside(
				this.gallerySelectorInner
			).addEvents({
				'mouseover': function(myself){
					myself.button.addClass('hover');
				}.pass(galleryItem, this),
				'mouseout': function(myself){
					myself.button.removeClass('hover');
				}.pass(galleryItem, this),
				'click': function(myself, number){
					this.changeGallery.pass(number,this)();
				}.pass([galleryItem, index], this)
			}).setStyle('width', galleryButtonWidth);
			
			galleryItem.button = button;
			var thumbnail = "";
			if (this.options.showCarousel)
				thumbnail = galleryItem.elements[0].thumbnail;
			else
				thumbnail = galleryItem.elements[0].image;
			new Element('div').addClass('preview').setStyle(
				'backgroundImage',
				"url('" + thumbnail + "')"
			).injectInside(button);
			new Element('h3').setHTML(galleryItem.title).injectInside(button);
			new Element('p').addClass('info').setHTML(formatString(this.options.textGalleryInfo, galleryItem.elements.length)).injectInside(button);
		}, this);
		new Element('br').injectInside(this.gallerySelectorInner).setStyle('clear','both');
	},
	toggleGallerySelector: function(state) {
		if (state)
			this.gallerySelector.start({'opacity' : .8}).element.setStyle('display','block');
		else
			this.gallerySelector.start({'opacity' : 0});
	},
	initHistory: function() {
		this.fireEvent('onHistoryInit');
		this.historyKey = this.galleryElement.id + '-gallery';
		if (this.options.customHistoryKey)
			this.historyKey = this.options.customHistoryKey();
		this.history = HistoryManager.register(
			this.historyKey,
			[1,1],
			function(values) {
				this.changeGallery.pass(parseInt(values[0]) - 1, this).delay(10);
				if(this.gallerySelector)
					this.toggleGallerySelector.pass(false, this).delay(500);
				this.goTo.pass(parseInt(values[1]) - 1, this).delay(100);
			}.bind(this),
			function(values) {
				return [this.historyKey, '(', values[0], ')', '-picture','(', values[1], ')'].join('');
			}.bind(this),
			this.historyKey + '\\((\\d+)\\)-picture\\((\\d+)\\)');
		updateHistory = function(){
			this.history.setValue(0, this.currentGallery + 1);
			this.history.setValue(1, this.currentIter + 1);
		}.bind(this);		
		
		this.addEvent('onChanged', updateHistory);
		this.addEvent('onGalleryChanged', updateHistory);
		this.fireEvent('onHistoryInited');
	}
});
