
if(typeof jQuery == 'undefined') {

	/*
		This file is part of JonDesign's SmoothGallery v1.0.1.

		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 2 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.
		Many thanks to:
		- The mootools team for the great mootools lib, and it's help and support throughout the project.
	*/


	var $removeEvents = function (object, type)
	{
		if (!object.events) return object;
		if (type){
			if (!object.events[type]) return object;
			for (var fn in object.events[type]) object.removeEvent(type, fn);
			object.events[type] = null;
		} else {
			for (var evType in object.events) object.removeEvents(evType);
			object.events = null;
		}
		return object;
	};

	// declaring the class
	var gallery = new Class({
		initialize: function(element, options) {
			this.setOptions({
				showArrows: true,
				showCarousel: true,
				showInfopane: false,
				thumbHeight: 75,
				thumbWidth: 100,
				thumbSpacing: 10,
				embedLinks: true,
				fadeDuration: 500,
				timed: false,
				delay: 9000,
				preloader: true,
				manualData: [],
				populateData: true,
				elementSelector: "div.imageElement",
				titleSelector: "h3",
				subtitleSelector: "p",
				linkSelector: "a.open",
				imageSelector: "img.full",
				thumbnailSelector: "img.thumbnail",
				//slideInfoZoneOpacity: 0.7,
				//edited by JR (Jul 18, 2007)
				//hides slide info while still allowing
				//the carousel to function properly
				slideInfoZoneOpacity: 0.0,
				carouselMinimizedOpacity: 0.4,
				carouselMinimizedHeight: 20,
				carouselMaximizedOpacity: 0.7,
				destroyAfterPopulate: true,
				baseClass: 'jdGallery',
				withArrowsClass: 'withArrows',
				textShowCarousel: 'Pictures',
				useThumbGenerator: false,
				thumbGenerator: 'resizer.php'
			}, 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);
			if (this.options.populateData)
				this.populateData();
			element.style.display="block";

			if (this.options.embedLinks)
			{
				this.currentLink = new Element('a').addClass('open').setProperties({
					href: '#',
					title: ''
				}).injectInside(element);
				if ((!this.options.showArrows) && (!this.options.showCarousel))
					this.galleryElement = element = this.currentLink;
				else
					this.currentLink.setStyle('display', 'none');
			}

			this.constructElements();
			if ((data.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);
			if (this.options.showInfopane) this.initInfoSlideshow();
			if (this.options.showCarousel) this.initCarousel();
			this.doSlideShow(1);
		},
		populateData: function() {
			currentArrayPlace = this.galleryData.length;
			options = this.options;
			data = this.galleryData;
			this.galleryElement.getElements(options.elementSelector).each(function(el) {
				elementDict = {
					image: el.getElement(options.imageSelector).getProperty('src'),
					number: currentArrayPlace
				};
				if ((options.showInfopane) | (options.showCarousel))
					Object.extend(elementDict, {
						title: el.getElement(options.titleSelector).innerHTML,
						description: el.getElement(options.subtitleSelector).innerHTML
					});
				if (options.embedLinks)
					Object.extend(elementDict, {
						link: el.getElement(options.linkSelector).href||false,
						linkTitle: el.getElement(options.linkSelector).title||false
					});
				if ((!options.useThumbGenerator) && (options.showCarousel))
					Object.extend(elementDict, {
						thumbnail: el.getElement(options.thumbnailSelector).src
					});
				else if (options.useThumbGenerator)
					Object.extend(elementDict, {
						thumbnail: 'resizer.php?imgfile=' + elementDict.image + '&max_width=' + options.thumbWidth + '&max_height=' + options.thumbHeight
					});

				data[currentArrayPlace] = elementDict;
				currentArrayPlace++;
				if (this.options.destroyAfterPopulate)
					el.remove();
			});
			this.galleryData = data;
			this.fireEvent('onPopulated');
		},
		constructElements: function() {
			el = this.galleryElement;
			this.maxIter = this.galleryData.length;
			var currentImg;
			for(i=0;i<this.galleryData.length;i++)
			{
				var currentImg = new Fx.Style(
					new Element('div').addClass('slideElement').setStyles({
						'position':'absolute',
						//Edited by JR [6-11-07]
						//'left':'0px',
						//'left':'50px',
						'right':'0px',
						'margin':'0px',
						'padding':'0px',
						'backgroundImage':"url('" + this.galleryData[i].image + "')",
						'backgroundPosition':"center center",
						'opacity':'0'
					}).injectInside(el),
					'opacity',
					{duration: this.options.fadeDuration}
				);
				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 = 0;
			this.galleryInit = 0;
			this.galleryElements[parseInt(this.currentIter)].set(1);
			if (this.options.showInfopane)
				this.showInfoSlideShow.delay(1000, this);
			this.prepareTimer();
			if (this.options.embedLinks)
				this.makeLink(this.currentIter);
		},
		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.embedLinks)
				this.clearLink();
			if (this.options.showInfopane)
			{
				this.slideInfoZone.clearChain();
				this.hideInfoSlideShow().chain(this.changeItem.pass(num, this));
			} else
				this.changeItem.delay(500, this, num);
			if (this.options.embedLinks)
				this.makeLink(num);
			this.prepareTimer();
			//Edited by Aaron
			//if (this.options.showCarousel)
			//	this.clearThumbnailsHighlights();
			//Edited by JR [6-12-07]
			this.setThumbnailsHighlights(this.thumbnailElements[num]);
		},
		changeItem: function(num) {
			this.fireEvent('onStartChanging');
			this.galleryInit = 0;
			if (this.currentIter != num)
			{
				for(i=0;i<this.maxIter;i++)
				{
				// Edited by Sam, 9/3, hide the element currently not being
				// displayed.
					if((i != num)) this.galleryElements[i].hide(this.options.fadeDuration);
				// This doesn't seem to work nor do anything...but I'll leave it in anyway
					if ((i != this.currentIter)) this.galleryElements[i].set(0);
				}
				if (num > this.currentIter) this.galleryElements[num].custom(1);
				else
				{
					this.galleryElements[num].set(1);
					this.galleryElements[this.currentIter].custom(0);
				}
				this.currentIter = num;
			}
			this.doSlideShow.bind(this)();
			this.fireEvent('onChanged');
		},
		clearTimer: function() {
			if (this.options.timed)
				$clear(this.timer);
		},
		prepareTimer: function() {
			if (this.options.timed)
				this.timer = this.nextItem.delay(this.options.delay, this);
		},
		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;
			} else {
				if (this.options.showInfopane)
				{
					if (this.options.showInfopane)
					{
						this.showInfoSlideShow.delay((500 + this.options.fadeDuration), this);
					} else
						if (this.options.showCarousel)
							this.centerCarouselOn(position);
				}
			}
		},
		initCarousel: function () {
			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;

			// Edited by JR [6-11-07]
			//this.carouselContainer.set({'opacity': this.options.carouselMinimizedOpacity, 'top': (this.options.carouselMinimizedHeight - this.carouselContainer.normalHeight)});

			//This block controls the position of the carousel show/hide label. Commented out so that it does not appear.
			/*
			this.carouselBtn = new Element('a').addClass('carouselBtn').setProperties({
				title: this.options.textShowCarousel
			}).setHTML(this.options.textShowCarousel).injectInside(carouselContainerElement);

			this.carouselBtn.addEvent(
				'click',
				function () {
					this.carouselContainer.clearTimer();
					this.toggleCarousel();
				}.bind(this)
			);
			*/

			this.carouselActive = false;

			var carouselElement = new Element('div').addClass('carousel').injectInside(carouselContainerElement);
			this.carousel = new Fx.Styles(carouselElement);

			this.carouselLabel = new Element('p').addClass('label').injectInside(this.carousel.element);
			this.carouselWrapper = new Element('div').addClass('carouselWrapper').injectInside(this.carousel.element);
			this.carouselInner = new Element('div').addClass('carouselInner').injectInside(this.carouselWrapper);

			this.carouselWrapper.scroller = new Scroller(this.carouselWrapper, {
				area: 100,
				velocity: 0.2
			})

			this.carouselWrapper.elementScroller = new Fx.Scroll(this.carouselWrapper, {
				duration: 400,
				onStart: this.carouselWrapper.scroller.stop.bind(this.carouselWrapper.scroller),
				onComplete: this.carouselWrapper.scroller.start.bind(this.carouselWrapper.scroller)
			});

			this.constructThumbnails();

			this.carouselInner.style.width = ((this.maxIter * (this.options.thumbWidth + this.options.thumbSpacing)) - this.options.thumbSpacing + this.options.thumbWidth) + "px";
		},
		toggleCarousel: function() {
			if (this.carouselActive)
				this.hideCarousel();
			else
				this.showCarousel();
		},
		showCarousel: function () {
			this.fireEvent('onShowCarousel');
			this.carouselContainer.custom({
				'opacity': this.options.carouselMaximizedOpacity,
				'top': 0
			}).addEvent('onComplete', function() { this.carouselActive = true; this.carouselWrapper.scroller.start(); }.bind(this));
		},
		hideCarousel: function () {
			this.fireEvent('onHideCarousel');
			this.carouselContainer.custom({
				'opacity': this.options.carouselMinimizedOpacity,
				'top': (this.options.carouselMinimizedHeight - this.carouselContainer.normalHeight)
			}).addEvent('onComplete', function() { this.carouselActive = false; this.carouselWrapper.scroller.stop(); }.bind(this));
		},
		constructThumbnails: function () {
			element = this.carouselInner;
			for(i=0;i<this.galleryData.length;i++)
			{
				//Edited by JR [6-11-07]
				/*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(0.2); */
				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 current thumbnail to "on" state (JR [6-11-07])
				if (i != 0) {
					currentImg.set(0.2);
				} else {
					currentImg.set(0.99);
					currentImg.selected = true;
				}
				currentImg.element.addEvents({
					'mouseover': function (myself) {
						myself.clearTimer();
						myself.custom(0.99);
						//Edited by JR [6-12-07]
						//$(this.carouselLabel).setHTML('<span class="number">' + (myself.relatedImage.number + 1) + "/" + this.maxIter + ":</span> " + myself.relatedImage.title);
						for (i=0; i<this.maxIter; i++) {
							if (myself != this.thumbnailElements[i] && !this.thumbnailElements[i].selected) {
								this.thumbnailElements[i].clearTimer();
								this.thumbnailElements[i].custom(0.2);
								this.thumbnailElements[i].selected = false;
							}
						}
					}.pass(currentImg, this),
					'mouseout': function (myself) {
						//Edited by JR [6-11-07]
						//myself.clearTimer();
						//myself.custom(0.2);
						if (!myself.selected) {
							myself.clearTimer();
							myself.custom(0.2);
						}
					}.pass(currentImg, this),
					'click': function (myself) {
						this.goTo(myself.relatedImage.number);
					}.pass(currentImg, this)
				});

				currentImg.relatedImage = this.galleryData[i];
				this.thumbnailElements[parseInt(i)] = currentImg;
			}
		},
		//Added by JR [6-12-07]
		setThumbnailsHighlights: function(currentThumb)
		{
			for (i=0; i<this.maxIter; i++) {
				if (currentThumb != this.thumbnailElements[i]) {
					this.thumbnailElements[i].clearTimer();
					this.thumbnailElements[i].custom(0.2);
					this.thumbnailElements[i].selected = false;
				} else {
					this.thumbnailElements[i].clearTimer();
					this.thumbnailElements[i].custom(0.99);
					this.thumbnailElements[i].selected = true;
				}
			}
		},
		clearThumbnailsHighlights: function()
		{
			for(i=0;i<this.galleryData.length;i++)
			{
				this.thumbnailElements[i].clearTimer();
				this.thumbnailElements[i].custom(0.2);
			}
		},
		centerCarouselOn: function(num) {
			var carouselElement = this.thumbnailElements[num];
			var position = carouselElement.element.offsetLeft + (carouselElement.element.offsetWidth / 2);
			var carouselWidth = this.carouselWrapper.offsetWidth;
			var carouselInnerWidth = this.carouselInner.offsetWidth;
			var diffWidth = carouselWidth / 2;
			var scrollPos = position-diffWidth;
			//Some problem with this line in IE6 - JR [6-12-07]
			this.carouselWrapper.elementScroller.scrollTo(scrollPos,0);
		},
		initInfoSlideshow: function() {
			//Added by Aaron?
			/*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(this.galleryData[this.currentIter].title);
			element.getElement('p').setHTML(this.galleryData[this.currentIter].description);
			this.slideInfoZone.custom({'opacity': [0, this.options.slideInfoZoneOpacity], 'height': [0, this.slideInfoZone.normalHeight]});
			if (this.options.showCarousel)
				this.slideInfoZone.chain(this.centerCarouselOn.pass(this.currentIter, this));
			return this.slideInfoZone;
		},
		hideInfoSlideShow: function() {
			this.fireEvent('onHideInfopane');
			this.slideInfoZone.clearTimer();
			this.slideInfoZone.custom({'opacity': 0, 'height': 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');
		}
	});
	gallery.implement(new Events);
	gallery.implement(new Options);

	/* All code copyright 2006 Jonathan Schemoul */
}