//** Featured Content Slider script- (c) Dynamic Drive DHTML code library: http://www.dynamicdrive.com.
//** May 2nd, 08'- Script rewritten and updated to 2.0.
//** June 12th, 08'- Script updated to v 2.3, which adds the following features:
			//1) Changed behavior of script to actually collapse the previous content when the active one is shown, instead of just tucking it underneath the later.
			//2) Added setting to reveal a content either via "click" or "mouseover" of pagination links (default is former).
			//3) Added public function for jumping to a particular slide within a Featured Content instance using an arbitrary link, for example.

//** July 11th, 08'- Script updated to v 2.4:
			//1) Added ability to select a particular slide when the page first loads using a URL parameter (ie: mypage.htm?myslider=4 to select 4th slide in "myslider")
			//2) Fixed bug where the first slide disappears when the mouse clicks or mouses over it when page first loads.

var featuredcontentslider={

//3 variables below you can customize if desired:
ajaxloadingmsg: '<div style="margin: 20px 0 0 20px"><img src="loading.gif" /> Fetching slider Contents. Please wait...</div>',
bustajaxcache: true, //bust caching of external ajax page after 1st request?
enablepersist: true, //persist to last content viewed when returning to page?

settingcaches: {}, //object to cache "setting" object of each script instance

jumpTo:function(fcsid, pagenumber){ //public function to go to a slide manually.
	this.turnpage(this.settingcaches[fcsid], pagenumber)
},

ajaxconnect:function(setting){
	var page_request = false
	if (window.ActiveXObject){ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
		try {
		page_request = new ActiveXObject("Msxml2.XMLHTTP")
		} 
		catch (e){
			try{
			page_request = new ActiveXObject("Microsoft.XMLHTTP")
			}
			catch (e){}
		}
	}
	else if (window.XMLHttpRequest) // if Mozilla, Safari etc
		page_request = new XMLHttpRequest()
	else
		return false
	var pageurl=setting.contentsource[1]
	page_request.onreadystatechange=function(){
		featuredcontentslider.ajaxpopulate(page_request, setting)
	}
	document.getElementById(setting.id).innerHTML=this.ajaxloadingmsg
	var bustcache=(!this.bustajaxcache)? "" : (pageurl.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime()
	page_request.open('GET', pageurl+bustcache, true)
	page_request.send(null)
},

ajaxpopulate:function(page_request, setting){
	if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1)){
		document.getElementById(setting.id).innerHTML=page_request.responseText
		this.buildpaginate(setting)
	}
},

buildcontentdivs:function(setting){
	var alldivs=document.getElementById(setting.id).getElementsByTagName("div")
	for (var i=0; i<alldivs.length; i++){
		if (this.css(alldivs[i], "contentdiv", "check")){ //check for DIVs with class "contentdiv"
			setting.contentdivs.push(alldivs[i])
				alldivs[i].style.display="none" //collapse all content DIVs to begin with
		}
	}
},

buildpaginate:function(setting){
	this.buildcontentdivs(setting)
	var sliderdiv=document.getElementById(setting.id)
	var pdiv=document.getElementById("paginate-"+setting.id)
	var phtml=""
	var toc=setting.toc
	var nextprev=setting.nextprev
	if (typeof toc=="string" && toc!="markup" || typeof toc=="object"){
		for (var i=1; i<=setting.contentdivs.length; i++){
			phtml+='<a href="#'+i+'" class="toc">'+(typeof toc=="string"? toc.replace(/#increment/, i) : toc[i-1])+'</a> '
		}
		phtml=(nextprev[0]!=''? '<a href="#prev" class="prev">'+nextprev[0]+'</a> ' : '') + phtml + (nextprev[1]!=''? '<a href="#next" class="next">'+nextprev[1]+'</a>' : '')
		pdiv.innerHTML=phtml
	}
	var pdivlinks=pdiv.getElementsByTagName("a")
	var toclinkscount=0 //var to keep track of actual # of toc links
	for (var i=0; i<pdivlinks.length; i++){
		if (this.css(pdivlinks[i], "toc", "check")){
			if (toclinkscount>setting.contentdivs.length-1){ //if this toc link is out of range (user defined more toc links then there are contents)
				pdivlinks[i].style.display="none" //hide this toc link
				continue
			}
			pdivlinks[i].setAttribute("rel", ++toclinkscount) //store page number inside toc link
			pdivlinks[i][setting.revealtype]=function(){
				featuredcontentslider.turnpage(setting, this.getAttribute("rel"))
				return false
			}
			setting.toclinks.push(pdivlinks[i])
		}
		else if (this.css(pdivlinks[i], "prev", "check") || this.css(pdivlinks[i], "next", "check")){ //check for links with class "prev" or "next"
			pdivlinks[i].onclick=function(){
				featuredcontentslider.turnpage(setting, this.className)
				return false
			}
		}
	}
	this.turnpage(setting, setting.currentpage, true)
	if (setting.autorotate[0]){ //if auto rotate enabled
		pdiv[setting.revealtype]=function(){
			featuredcontentslider.cleartimer(setting, window["fcsautorun"+setting.id])
		}
		sliderdiv["onclick"]=function(){ //stop content slider when slides themselves are clicked on
			featuredcontentslider.cleartimer(setting, window["fcsautorun"+setting.id])
		}
		setting.autorotate[1]=setting.autorotate[1]+(1/setting.enablefade[1]*50) //add time to run fade animation (roughly) to delay between rotation
	 this.autorotate(setting)
	}
},

urlparamselect:function(fcsid){
	var result=window.location.search.match(new RegExp(fcsid+"=(\\d+)", "i")) //check for "?featuredcontentsliderid=2" in URL
	return (result==null)? null : parseInt(RegExp.$1) //returns null or index, where index (int) is the selected tab's index
},

turnpage:function(setting, thepage, autocall){
	var currentpage=setting.currentpage //current page # before change
	var totalpages=setting.contentdivs.length
	var turntopage=(/prev/i.test(thepage))? currentpage-1 : (/next/i.test(thepage))? currentpage+1 : parseInt(thepage)
	turntopage=(turntopage<1)? totalpages : (turntopage>totalpages)? 1 : turntopage //test for out of bound and adjust
	if (turntopage==setting.currentpage && typeof autocall=="undefined") //if a pagination link is clicked on repeatedly
		return
	setting.currentpage=turntopage
	setting.contentdivs[turntopage-1].style.zIndex=++setting.topzindex
	this.cleartimer(setting, window["fcsfade"+setting.id])
	setting.cacheprevpage=setting.prevpage
	if (setting.enablefade[0]==true){
		setting.curopacity=0
		this.fadeup(setting)
	}
	if (setting.enablefade[0]==false){ //if fade is disabled, fire onChange event immediately (verus after fade is complete)
		setting.contentdivs[setting.prevpage-1].style.display="none" //collapse last content div shown (it was set to "block")
		setting.onChange(setting.prevpage, setting.currentpage)
	}
	setting.contentdivs[turntopage-1].style.visibility="visible"
	setting.contentdivs[turntopage-1].style.display="block"
	if (setting.prevpage<=setting.toclinks.length) //make sure pagination link exists (may not if manually defined via "markup", and user omitted)
		this.css(setting.toclinks[setting.prevpage-1], "selected", "remove")
	if (turntopage<=setting.toclinks.length) //make sure pagination link exists (may not if manually defined via "markup", and user omitted)
		this.css(setting.toclinks[turntopage-1], "selected", "add")
	setting.prevpage=turntopage
	if (this.enablepersist)
		this.setCookie("fcspersist"+setting.id, turntopage)
},

setopacity:function(setting, value){ //Sets the opacity of targetobject based on the passed in value setting (0 to 1 and in between)
	var targetobject=setting.contentdivs[setting.currentpage-1]
	if (targetobject.filters && targetobject.filters[0]){ //IE syntax
		if (typeof targetobject.filters[0].opacity=="number") //IE6
			targetobject.filters[0].opacity=value*100
		else //IE 5.5
			targetobject.style.filter="alpha(opacity="+value*100+")"
	}
	else if (typeof targetobject.style.MozOpacity!="undefined") //Old Mozilla syntax
		targetobject.style.MozOpacity=value
	else if (typeof targetobject.style.opacity!="undefined") //Standard opacity syntax
		targetobject.style.opacity=value
	setting.curopacity=value
},



fadeup:function(setting){
	if (setting.curopacity<1){
		this.setopacity(setting, setting.curopacity+setting.enablefade[1])
		window["fcsfade"+setting.id]=setTimeout(function(){featuredcontentslider.fadeup(setting)}, 50)
	}
	else{ //when fade is complete
		if (setting.cacheprevpage!=setting.currentpage) //if previous content isn't the same as the current shown div (happens the first time the page loads/ script is run)
			setting.contentdivs[setting.cacheprevpage-1].style.display="none" //collapse last content div shown (it was set to "block")
		setting.onChange(setting.cacheprevpage, setting.currentpage)
	}
},

cleartimer:function(setting, timervar){
	if (typeof timervar!="undefined"){
		clearTimeout(timervar)
		clearInterval(timervar)
		if (setting.cacheprevpage!=setting.currentpage){ //if previous content isn't the same as the current shown div
			setting.contentdivs[setting.cacheprevpage-1].style.display="none"
		}
	}
},

css:function(el, targetclass, action){
	var needle=new RegExp("(^|\\s+)"+targetclass+"($|\\s+)", "ig")
	if (action=="check")
		return needle.test(el.className)
	else if (action=="remove")
		el.className=el.className.replace(needle, "")
	else if (action=="add")
		el.className+=" "+targetclass
},

autorotate:function(setting){
 window["fcsautorun"+setting.id]=setInterval(function(){featuredcontentslider.turnpage(setting, "next")}, setting.autorotate[1])
},

getCookie:function(Name){ 
	var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
	if (document.cookie.match(re)) //if cookie found
		return document.cookie.match(re)[0].split("=")[1] //return its value
	return null
},

setCookie:function(name, value){
	document.cookie = name+"="+value

},


init:function(setting){
	var persistedpage=this.getCookie("fcspersist"+setting.id) || 1
	var urlselectedpage=this.urlparamselect(setting.id) //returns null or index from: mypage.htm?featuredcontentsliderid=index
	this.settingcaches[setting.id]=setting //cache "setting" object
	setting.contentdivs=[]
	setting.toclinks=[]
	setting.topzindex=0
	setting.currentpage=urlselectedpage || ((this.enablepersist)? persistedpage : 1)
	setting.prevpage=setting.currentpage
	setting.revealtype="on"+(setting.revealtype || "click")
	setting.curopacity=0
	setting.onChange=setting.onChange || function(){}
	if (setting.contentsource[0]=="inline")
		this.buildpaginate(setting)
	if (setting.contentsource[0]=="ajax")
		this.ajaxconnect(setting)
}

}

function isBody(element){
	return (/^(?:body|html)$/i).test(element.tagName);
};
Element.implement({
	getPosition: function(relative){
		if (isBody(this)) return {x: 0, y: 0};
		var el = this, position = {x: 0, y: 0};
		while (el){
			position.x += el.offsetLeft;
			position.y += el.offsetTop;
			el = el.offsetParent;
		}
		var rpos = (relative) ? $(relative).getPosition() : {x: 0, y: 0};
		return {x: position.x - rpos.x, y: position.y - rpos.y};
	}
});

// declaring the class
var gallery = {
	Implements: [Events, Options],
	options: {
		showArrows: true,
		showCarousel: true,
		showInfopane: true,
		embedLinks: 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",
		imageSelector: "img.full",
		thumbnailSelector: "img.thumbnail",
		defaultTransition: "fade",
		/* InfoPane options */
		slideInfoZoneOpacity: 0.7,
		slideInfoZoneSlide: true,
		/* Carousel options */
		carouselMinimizedOpacity: 0.4,
		carouselMinimizedHeight: 20,
		carouselMaximizedOpacity: 0.9,
		thumbHeight: 75,
		thumbWidth: 100,
		thumbSpacing: 10,
		thumbIdleOpacity: 0.2,
		textShowCarousel: 'Pictures',
		showCarouselLabel: true,
		thumbCloseCarousel: true,
		useThumbGenerator: false,
		thumbGenerator: 'resizer.php',
		useExternalCarousel: false,
		carouselElement: false,
		carouselHorizontal: true,
		activateCarouselScroller: true,
		carouselPreloader: true,
		textPreloadingCarousel: 'Loading...',
		/* CSS Classes */
		baseClass: 'jdGallery',
		withArrowsClass: 'withArrows',
		/* Plugins: HistoryManager */
		useHistoryManager: false,
		customHistoryKey: false,
		/* Plugins: ReMooz */
		useReMooz: false
	},
	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);
		
		if (this.options.useReMooz&&(this.options.defaultTransition=="fade"))
			this.options.defaultTransition="crossfade";
		
		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.options.useReMooz))
		{
			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 ((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);
		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;
		element.getElements(options.elementSelector).each(function(el) {
			elementDict = $H({
				image: el.getElement(options.imageSelector).getProperty('src'),
				number: currentArrayPlace,
				transition: this.options.defaultTransition
			});
			if ((options.showInfopane) | (options.showCarousel))
				elementDict.extend({
					title: el.getElement(options.titleSelector).innerHTML,
					description: el.getElement(options.subtitleSelector).innerHTML
				});
			if ((options.embedLinks) | (options.useReMooz))
				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')
				});
			else if (options.useThumbGenerator)
				elementDict.extend({
					thumbnail: options.thumbGenerator + '?imgfile=' + elementDict.image + '&max_width=' + options.thumbWidth + '&max_height=' + options.thumbHeight
				});
			
			data.extend([elementDict]);
			currentArrayPlace++;
			if (this.options.destroyAfterPopulate)
				el.dispose();
		});
		return data;
	},
	constructElements: function() {
		el = this.galleryElement;
		if (this.options.embedLinks && (!this.options.showArrows))
			el = this.currentLink;
		this.maxIter = this.galleryData.length;
		var currentImg;
		for(i=0;i<this.galleryData.length;i++)
		{
			var currentImg = new Fx.Morph(
				new Element('div').addClass('slideElement').setStyles({
					'position':'absolute',
					'left':'0px',
					'right':'0px',
					'margin':'0px',
					'padding':'0px',
					'backgroundPosition':"center center",
					'opacity':'0'
				}).injectInside(el),
				{duration: this.options.fadeDuration}
			);
			if (this.options.preloader)
			{
				currentImg.source = this.galleryData[i].image;
				currentImg.loaded = false;
				currentImg.load = function(imageStyle, i) {
					if (!imageStyle.loaded)	{
						this.galleryData[i].imgloader = new Asset.image(imageStyle.source, {
		                            'onload'  : function(img, i){
													img.element.setStyle(
													'backgroundImage',
													"url('" + img.source + "')")
													img.loaded = true;
													img.width = this.galleryData[i].imgloader.width;
													img.height = this.galleryData[i].imgloader.height;
												}.pass([imageStyle, i], this)
						});
					}
				}.pass([currentImg, i], 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 = 0;
		this.galleryInit = 0;
		this.galleryElements[parseInt(this.currentIter)].set({opacity: 1});
		if (this.options.showInfopane)
			this.showInfoSlideShow.delay(1000, this);
		if (this.options.useReMooz)
			this.makeReMooz.delay(1000, this);
		var textShowCarousel = formatString(this.options.textShowCarousel, this.currentIter+1, this.maxIter);
		if (this.options.showCarousel&&(!this.options.carouselPreloader)&&(!this.options.useExternalCarousel))
			this.carouselBtn.set('html', textShowCarousel).setProperty('title', textShowCarousel);
		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.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)
		{
			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;
			if (this.options.useReMooz)
				this.makeReMooz();
		}
		var textShowCarousel = formatString(this.options.textShowCarousel, num+1, this.maxIter);
		if ((this.options.showCarousel)&&(!this.options.useExternalCarousel))
			this.carouselBtn.set('html', textShowCarousel).setProperty('title', textShowCarousel);
		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;
			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.Morph(carouselContainerElement, {transition: Fx.Transitions.Expo.easeOut});
			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
			}).injectInside(carouselContainerElement);
			if(this.options.carouselPreloader)
				this.carouselBtn.set('html', this.options.textPreloadingCarousel);
			else
				this.carouselBtn.set('html', this.options.textShowCarousel);
			this.carouselBtn.addEvent(
				'click',
				function () {
					this.carouselContainer.cancel();
					this.toggleCarousel();
				}.bind(this)
			);
			this.carouselActive = false;
	
			carouselElement = new Element('div').addClass('carousel').injectInside(carouselContainerElement);
			this.carousel = new Fx.Morph(carouselElement);
		} else {
			carouselElement = $(this.options.carouselElement).addClass('jdExtCarousel');
		}
		this.carouselElement = new Fx.Morph(carouselElement, {transition: Fx.Transitions.Expo.easeOut});
		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.Morph(carouselWrapper, {transition: Fx.Transitions.Expo.easeOut});
		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";
		if (this.options.carouselHorizontal)
			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.dispose();
			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.Morph(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), {duration: 200}).start({
					'opacity': this.options.thumbIdleOpacity
				});
			currentImg.element.addEvents({
				'mouseover': function (myself) {
					myself.cancel();
					myself.start({'opacity': 0.99});
					if (this.options.showCarouselLabel)
						$(this.carouselLabel).set('html', '<span class="number">' + (myself.relatedImage.number + 1) + "/" + this.maxIter + ":</span> " + myself.relatedImage.title);
				}.pass(currentImg, this),
				'mouseout': function (myself) {
					myself.cancel();
					myself.start({'opacity': this.options.thumbIdleOpacity});
				}.pass(currentImg, this),
				'click': function (myself) {
					this.goTo(myself.relatedImage.number);
					if (this.options.thumbCloseCarousel&&(!this.options.useExternalCarousel))
						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();
		if (!this.options.useExternalCarousel)
			this.thumbnailPreloader.addEvent('onComplete', function() {
				var textShowCarousel = formatString(this.options.textShowCarousel, this.currentIter+1, this.maxIter);
				this.carouselBtn.set('html', textShowCarousel).setProperty('title', textShowCarousel);
			}.bind(this));
		this.thumbnailPreloader.load(thumbnails);
	},
	clearThumbnailsHighlights: function()
	{
		for(i=0;i<this.galleryData.length;i++)
		{
			this.thumbnailElements[i].cancel();
			this.thumbnailElements[i].start(0.2);
		}
	},
	changeThumbnailsSize: function(width, height)
	{
		for(i=0;i<this.galleryData.length;i++)
		{
			this.thumbnailElements[i].cancel();
			this.thumbnailElements[i].element.setStyles({
				'width': width + "px",
				'height': height + "px"
			});
		}
	},
	centerCarouselOn: function(num) {
		if (!this.carouselWallMode)
		{
			var carouselElement = this.thumbnailElements[num];
			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;
			this.carouselWrapper.elementScroller.start(scrollPos,0);
		}
	},
	initInfoSlideshow: function() {
		/*if (this.slideInfoZone.element)
			this.slideInfoZone.element.remove();*/
		this.slideInfoZone = new Fx.Morph(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.cancel();
		element = this.slideInfoZone.element;
		element.getElement('h2').set('html', this.galleryData[this.currentIter].title);
		element.getElement('p').set('html', 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));
		return this.slideInfoZone;
	},
	hideInfoSlideShow: function() {
		this.fireEvent('onHideInfopane');
		this.slideInfoZone.cancel();
		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');
	},
	makeReMooz: function() {
		this.currentLink.setProperties({
			href: '#'
		});
		this.currentLink.setStyles({
			'display': 'block'
		});
		
		this.galleryElements[this.currentIter].element.set('title', this.galleryData[this.currentIter].title + ' :: ' + this.galleryData[this.currentIter].description);
		this.ReMooz = new ReMooz(this.galleryElements[this.currentIter].element, {
			link: this.galleryData[this.currentIter].link,
			shadow: false,
			dragging: false,
			addClick: false,
			resizeOpacity: 1
		});
		var img = this.galleryElements[this.currentIter];
		var coords = img.element.getCoordinates();
		delete coords.right;
		delete coords.bottom;
		
		widthDiff = coords.width - img.width;
		heightDiff = coords.height - img.height;
		
		coords.width = img.width;
		coords.height = img.height;
		
		coords.left += Math.ceil(widthDiff/2)+1;
		coords.top += Math.ceil(heightDiff/2)+1;
		
		this.ReMooz.getOriginCoordinates = function(coords) {
			return coords;
		}.bind(this, coords);
		this.currentLink.onclick = function () {
			this.ReMooz.open.bind(this.ReMooz)();
			return false;
		}.bind(this);
	},
	/* To change the gallery data, those two functions : */
	flushGallery: function() {
		this.galleryElements.each(function(myFx) {
			myFx.element.dispose();
			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 = new History.Route({
			defaults: [1],
			pattern: this.historyKey + '\\((\\d+)\\)',
			generate: function(values) {
				return [this.historyKey, '(', values[0], ')'].join('')
			}.bind(this),
			onMatch: function(values, defaults) {
				if (parseInt(values[0])-1 < this.maxIter)
					this.goTo(parseInt(values[0])-1);
			}.bind(this)
		});
		this.addEvent('onChanged', function(){
			this.history.setValue(0, this.currentIter+1);
			this.history.defaults=[this.currentIter+1];
		}.bind(this));
		this.fireEvent('onHistoryInited');
	}
};
gallery = new Class(gallery);

gallery.Transitions = new Hash ({
	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));
	}
});

/* 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);
  }
  
});

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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; 
}var ReMooz = new Class({

	Implements: [Events, Options, Chain],

	options: {
		link: null,
		type: 'image',
		container: null,
		className: null,
		centered: false,
		dragging: true,
		closeOnClick: true,
		shadow: (Browser.Engine.trident) ? 'onOpenEnd' : 'onOpen', // performance
		resize: true,
		margin: 20,
		resizeFactor: 0.95,
		resizeLimit: false, // {x: 640, y: 640}
		fixedSize: false,
		cutOut: true,
		addClick: true,
		opacityLoad: 0.6,
		opacityResize: 1,
		opacityTitle: 0.9,
		resizeOptions: {},
		fxOptions: {},
		closer: true,
		parse: false, // 'rel'
		parseSecure: false,
		temporary: false,
		onBuild: $empty,
		onLoad: $empty,
		onOpen: $empty,
		onOpenEnd: $empty,
		onClose: $empty,
		onCloseEnd: $empty,
		generateTitle: function(el) {
			var text = el.get('title');
			if (!text) return false;
			var title = text.split(' :: ');
			var head = new Element('h6', {'html': title[0]});
			return (title[1]) ? [head, new Element('p', {'html': title[1]})] : head;
		}
	},

	initialize: function(element, options) {
		this.element = $(element);
		this.setOptions(options);
		if (this.options.parse) {
			var obj = this.element.getProperty(this.options.parse);
			if (obj && (obj = JSON.decode(obj, this.options.parseSecure))) this.setOptions(obj);
		}
		var origin = this.options.origin;
		this.origin = ((origin) ? $(origin) || this.element.getElement(origin) : null) || this.element;
		this.link = this.options.link || this.element.get('href') || this.element.get('src');
		this.container = $(this.options.container) || this.element.getDocument();
		this.bound = {
			'click': function(e) {
				this.open.delay(1, this);
				return false;
			}.bind(this),
			'close': this.close.bind(this),
			'dragClose': function(e) {
				if (e.rightClick) return;
				this.close();
			}.bind(this)
		};
		if (this.options.addClick) this.bindToElement();
	},

	destroy: function() {
		if (this.box) this.box.destroy();
		this.box = this.tweens = this.body = this.content = null;
	},

	bindToElement: function(element) {
		($(element) || this.element).addClass('remooz-element').addEvent('click', this.bound.click);
		return this;
	},

	getOriginCoordinates: function() {
		var coords = this.origin.getCoordinates();
		delete coords.right;
		delete coords.bottom;
		return coords;
	},

	open: function(e) {
		if (this.opened) return (e) ? this.close() : this;
		this.opened = this.loading = true;
		if (!this.box) this.build();
		this.coords = this.getOriginCoordinates();
		this.coords.opacity = this.options.opacityLoad;
		this.coords.display = '';
		this.tweens.box.set(this.coords);
		this.box.addClass('remooz-loading');
		ReMooz.open(this.fireEvent('onLoad'));
		this['open' + this.options.type.capitalize()]();
		return this;
	},

	finishOpen: function() {
		this.tweens.fade.start(0, 1);
		this.drag.attach();
		this.fireEvent('onOpenEnd').callChain();
	},

	close: function() {
		if (!this.opened) return this;
		this.opened = false;
		ReMooz.close(this.fireEvent('onClose'));
		if (this.loading) {
			this.box.setStyle('display', 'none');
			return this;
		}
		this.drag.detach();
		this.tweens.fade.cancel().set(0).fireEvent('onComplete');
		if (this.tweens.box.timer) this.tweens.box.clearChain();
		var vars = this.getOriginCoordinates();
		if (this.options.opacityResize != 1) vars.opacity = this.options.opacityResize;
		this.tweens.box.start(vars).chain(this.closeEnd.bind(this));
		return this;
	},

	closeEnd: function() {
		if (this.options.cutOut) this.element.setStyle('visibility', 'visible');
		this.box.setStyle('display', 'none');
		this.fireEvent('onCloseEnd').callChain();
		if (this.options.temporary) this.destroy();
	},

	openImage: function() {
		var tmp = new Image();
		tmp.onload = tmp.onabort = tmp.onerror = function(fast) {
			this.loading = tmp.onload = tmp.onabort = tmp.onerror = null;
			if (!tmp.width || !this.opened) {
				this.fireEvent('onError').close();
				return;
			}
			var to = {x: tmp.width, y: tmp.height};
			if (!this.content) this.content = $(tmp).inject(this.body);
			else tmp = null;
			this[(this.options.resize) ? 'zoomRelativeTo' : 'zoomTo'].create({
				'delay': (tmp && fast !== true) ? 1 : null,
				'arguments': [to],
				'bind': this
			})();
		}.bind(this);
		tmp.src = this.link;
		if (tmp && tmp.complete && tmp.onload) tmp.onload(true);
	},

	/**
	 * @todo Test implementation
	 */
	openElement: function() {
		this.content = this.content || $(this.link) || $E(this.link);
		if (!this.content) {
			this.fireEvent('onError').close();
			return;
		}
		this.content.inject(this.body);
		this.zoomTo({x: this.content.scrollWidth, y: this.content.scrollHeight});
	},

	zoomRelativeTo: function(to) {
		var scale = this.options.resizeLimit;
		if (!scale) {
			scale = this.container.getSize();
			scale.x *= this.options.resizeFactor;
			scale.y *= this.options.resizeFactor;
		}
		for (var i = 2; i--;) {
			if (to.x > scale.x) {
				to.y *= scale.x / to.x;
				to.x = scale.x;
			} else if (to.y > scale.y) {
				to.x *= scale.y / to.y;
				to.y = scale.y;
			}
		}
		return this.zoomTo({x: to.x.toInt(), y: to.y.toInt()});
	},

	zoomTo: function(to) {
		to = this.options.fixedSize || to;
		var box = this.container.getSize(), scroll = this.container.getScroll();
		var pos = (!this.options.centered) ? {
			x: (this.coords.left + (this.coords.width / 2) - to.x / 2).toInt()
				.limit(scroll.x + this.options.margin, scroll.x + box.x - this.options.margin - to.x),
			y: (this.coords.top + (this.coords.height / 2) - to.y / 2).toInt()
				.limit(scroll.y + this.options.margin, scroll.y + box.y - this.options.margin - to.y)
		} :  {
			x: scroll.x + ((box.x - to.x) / 2).toInt(),
			y: scroll.y + ((box.y - to.y) / 2).toInt()
		};
		if (this.options.cutOut) this.element.setStyle('visibility', 'hidden');
		this.box.removeClass('remooz-loading');
		var vars = {left: pos.x, top: pos.y, width: to.x, height: to.y};
		if (this.options.opacityResize != 1) vars.opacity = [this.options.opacityResize, 1];
		else this.box.set('opacity', 1);
		this.tweens.box.start(vars).chain(this.finishOpen.bind(this));
		this.fireEvent('onOpen');
	},

	build: function() {
		this.addEvent('onBlur', function() {
			this.focused = false;
			this.box.removeClass('remooz-box-focus').setStyle('z-index', ReMooz.options.zIndex);
		}, true);
		this.addEvent('onFocus', function() {
			this.focused = true;
			this.box.addClass('remooz-box-focus').setStyle('z-index', ReMooz.options.zIndexFocus);
		}, true);

		var classes = ['remooz-box', 'remooz-type-' + this.options.type, 'remooz-engine-' + Browser.Engine.name + Browser.Engine.version];
		if (this.options.className) classes.push(this.options.className);
		this.box = new Element('div', {
			'class': classes.join(' '),
			'styles': {
				'display': 'none',
				'top': 0,
				'left': 0,
				'zIndex': ReMooz.options.zIndex
			}
		});

		this.tweens = {
			'box': new Fx.Morph(this.box, $merge({
					'duration': 400,
					'unit': 'px',
					'transition': Fx.Transitions.Quart.easeOut,
					'chain': 'cancel'
				}, this.options.resizeOptions)
			),
			'fade': new Fx.Tween(null, $merge({
					'property': 'opacity',
					'duration': (Browser.Engine.trident) ? 0 : 300,
					'chain': 'cancel'
				}, this.options.fxOptions)).addEvents({
					'onComplete': function() {
						if (!this.element.get('opacity')) this.element.setStyle('display', 'none');
					},
					'onStart': function() {
						if (!this.element.get('opacity')) this.element.setStyle('display', '');
					}
				}
			)
		};
		this.tweens.fade.element = $$();

		if (this.options.shadow) {
			if (Browser.Engine.webkit420) {
				this.box.setStyle('-webkit-box-shadow', '0 0 10px rgba(0, 0, 0, 0.7)');
			} else if (!Browser.Engine.trident4) {
				var shadow = new Element('div', {'class': 'remooz-bg-wrap'}).inject(this.box);
				['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'].each(function(dir) {
					new Element('div', {'class': 'remooz-bg remooz-bg-' + dir}).inject(shadow);
				});
				this.tweens.bg = new Fx.Tween(shadow, {
					'property': 'opacity',
					'chain': 'cancel'
				}).set(0);
				this.addEvent(this.options.shadow, this.tweens.bg.set.bind(this.tweens.bg, 1), true);
				this.addEvent('onClose', this.tweens.bg.set.bind(this.tweens.bg, 0), true);
			}
		}

		if (this.options.closer) {
			var closer = new Element('a', {
				'class': 'remooz-btn-close',
				'events': {'click': this.bound.close}
			}).inject(this.box);
			this.tweens.fade.element.push(closer);
		}
		this.body = new Element('div', {'class': 'remooz-body'}).inject(this.box);

		var title = this.options.title || this.options.generateTitle.call(this, this.element);
		if (title) { // thx ie6
			var title = new Element('div', {'class': 'remooz-title'}).adopt(
				new Element('div', {'class': 'remooz-title-bg', 'opacity': this.options.opacityTitle}),
				new Element('div', {'class': 'remooz-title-content'}).adopt(title)
			).inject(this.box);
			this.tweens.fade.element.push(title);
		}
		this.tweens.fade.set(0).fireEvent('onComplete');

		this.drag = new Drag.Move(this.box, {
			'snap': 15,
			'preventDefault': true,
			'onBeforeStart': function() {
				if (!this.focused && !this.loading) ReMooz.focus(this);
				else if (this.loading || this.options.closeOnClick) this.box.addEvent('mouseup', this.bound.dragClose);
			}.bind(this),
			'onSnap': function() {
				this.box.removeEvent('mouseup', this.bound.dragClose);
				if (!this.options.dragging) this.drag.stop();
				else this.box.addClass('remooz-box-dragging');
			}.bind(this),
			'onComplete': function() {
				this.box.removeClass('remooz-box-dragging');
			}.bind(this)
		});
		this.drag.detach();

		this.fireEvent('onBuild', this.box, this.element);
		this.box.inject(this.element.getDocument().body);
	}

});

ReMooz.factory = function(extended) {
	return $extend(this, extended);
};

ReMooz.factory(new Options).factory({

	options: {
		zIndex: 41,
		zIndexFocus: 42,
		query: 'a.remooz',
		modal: false
	},

	assign: function(elements, options) {
		return $$(elements).map(function(element) {
			return new ReMooz(element, options);
		}, this);
	},

	stack: [],

	open: function(obj) {
		var last = this.stack.getLast();
		this.focus(obj);
		if (last && this.options.modal) last.close();
	},

	close: function(obj) {
		var length = this.stack.length - 1;
		if (length > 1 && this.stack[length] == obj) this.focus(this.stack[length - 1]);
		this.stack.erase(obj);
	},

	focus: function(obj) {
		var last = this.stack.getLast();
		obj.fireEvent('onFocus', [obj]);
		if (last == obj) return;
		if (last) last.fireEvent('onBlur', [last]);
		this.stack.erase(obj).push(obj);
	}

});
/**
 * MooHover - Anchor and form input modification
 *
 * @version		1.0.1
 *
 * @license		MIT-style license
 * @author		Constantin Boiangiu <constantin [at] php-help.ro>
 * @copyright	Author
 */

var MooHover = new Class({
	Implements: [Options],
	options: {
		container: null,
		className: 'MooTrans',
		defaultClass: 'default',
		duration: 400,
		transition: Fx.Transitions.Sine.easeOut		
	},

	initialize: function(options) {
		this.setOptions(options);
		this.container = $(this.options.container) || document;
		this.start();		
	},
	
	start: function(){
		var buttons = this.container.
					  getElements('.'+this.options.className).
					  filter(function(elem,i){
							if(elem.rel!=='selected')
								return elem;							
					   }.bind(this));
		
		buttons.each(function(element,i){
			element.setStyles({'opacity':0.001,'position':'absolute','top':0,'left':0});
			
			new Element('div',{
				'class':this.options.defaultClass,
				'text':element.get('text')||element.get('value')
			}).injectBefore(element).adopt(element);
			
			var transEffect = new Fx.Morph(element, {duration: this.options.duration, transition: this.options.transition});
			
			element.addEvents({
				'mouseover':function(){
					transEffect.cancel();
					transEffect.start({opacity:1});
				},
				'mouseout':function(){
					transEffect.cancel();
					transEffect.start({opacity:0.001});
				}
			})			
		}.bind(this));
	}
});

	function initImageZoom(_options) {
		var options = $extend({
			rel: 'imagezoom'
		}, _options || {});
		var elements = $$(document.links).filter(function(el) {
			if ((el.rel) && (el.rel.indexOf(options.rel) != -1)) 
				return true;
			else
				return false;
		});
		for (var i = 0; i < elements.length; i++) {
			var el = elements[i];
			el.addEvent("click", function() {
				this.blur();
				var sEl = this;
				var imgCap = "";
				if (this.getElements("img").length > 0)
					sEl = this.getElements("img")[0];
				if ((sEl.alt) && (sEl.alt != ""))
					imgCap = sEl.alt;
				else if (sEl.title)
					imgCap = sEl.title;
				else if (sEl.parentNode.title)
					imgCap = sEl.parentNode.title;
				var _options = $extend({
					image: this.href,
					caption: imgCap,
					startElement: sEl
				}, options || {});
				_options.image = this.href;
				_options.caption = imgCap;
				var imagezoom = new Imagezoom(_options);
				imagezoom.preloadImage();
				imagezoom.show();
				return false;
			});
		}
	}
	
	var Imagezoom = function(_options) {		
		var options = $extend({
			image: false,
			caption: "",
			enableCaptions: true,
			startElement: false,
			x: 10,
			y: 10,
			initWidth: 50,
			initHeight: 50,
			draggable: true,
			loadImage: "/loading.gif",
			loadDelay: 150,
			duration: 800,
			closeDuration: 500,
			transition: Fx.Transitions.Back.easeOut,
			startOpacity: 0.6,
			closeText: 'Close',
			rel: 'imagezoom',
			showCaptionBar: true,
			overlay: false,
			overlayColor: "#000",
			overlayOpacity: .75
		}, _options || {});
		
		var box = document.createElement("div");		
		var instance = this;
		
		/* shadow divs */
		var tl = document.createElement("div");
		tl.className = "s s_tl";
		var tr = document.createElement("div");
		tr.className = "s s_tr";
		var bl = document.createElement("div");
		bl.className = "s s_bl";
		var br = document.createElement("div");
		br.className = "s s_br";
		var top = document.createElement("div");
		top.className = "s s_top";
		var bottom = document.createElement("div");
		bottom.className = "s s_bottom";
		var left = document.createElement("div");
		left.className = "s s_left";
		var right = document.createElement("div");
		right.className = "s s_right";
		
		this.preloadImage = function() {
			if (options.image != false) {
				var img = new Image();
				img.src = options.image;
				img.style.visibility = "hidden";
				img.style.position = "absolute";
				img.style.top = "-9999999999px";
				img.setAttribute("id", "imagezoom-" + options.image);
				$$('body')[0].appendChild(img);
			}	
		}
		
		this.getImage = function() {
			if (($('imagezoom-' + options.image)) && ($('imagezoom-' + options.image).width != "0")) {
				var img = $('imagezoom-' + options.image).clone();
				img.setAttribute("id", "");
				img.style.position = "relative";
				img.style.top = "0px";
				img.style.visibility = "visible";
			} else {
				instance.preloadImage();
				window.setTimeout(function() {
					instance.getImage();
				}, 50);
			}
			return img;
		}		
		
		this.show = function() {
			if (options.image != false) {
				box.style.position = "absolute";
				box.style.overflow = "hidden";
				box.setAttribute("id", "imagezoom-open-" + options.image);
				
				if (options.startElement != false)
					options.startElement.blur();
				
				var x = options.x;
				var y = options.y;
				var boxWidth = options.initWidth;
				var boxHeight = options.initHeight;
				if (options.startElement != false) {
					x = options.startElement.getPosition().x;
					y = options.startElement.getPosition().y;
					boxWidth = options.startElement.offsetWidth;
					boxHeight = options.startElement.offsetHeight;
				}
				box.style.left = x + "px";
				box.style.top = y + "px";
				box.style.width = boxWidth + "px";
				box.style.height = boxHeight + "px";
				
				var fx = new Fx.Morph(box);
				fx.set({opacity: options.startOpacity});
				
				box.className = "imagezoom";
				$$('body')[0].appendChild(box);
				box.style.cursor = "pointer";
				box.addEvent("click", function() {
					var fx = new Fx.Morph(box, {duration: 200});
					fx.start({opacity: 0}).chain(function() {
						$$('body')[0].removeChild(box);
					});
				});

				this.loadImage();
			}
		}
		
		this.loadImage = function() {
			if (box.getElements(".loading").length == 0) {
				var loading = new Image();
				loading.src = options.loadImage;
				loading.className = "loading";
				box.appendChild(loading);
			}	
			if ($('imagezoom-' + options.image)) {
				var el = $('imagezoom-' + options.image);
				if (el.width != "0") {
					var newEl = new Image();
					newEl.src = options.image;
					window.setTimeout(function() { instance.insertImage(newEl) }, options.loadDelay);
				} else {
					window.setTimeout(function() { instance.loadImage(); }, 50);
				}
			} else {
				instance.preloadImage();
				window.setTimeout(function() { instance.loadImage(); }, 50);
			}
		}
		
		this.insertImage = function(img) {
			box.removeEvents("click");
			box.style.cursor = "default";
			box.style.overflow = "visible";
			var w = img.width;
			var h = img.height;
			img.style.width = w + "px";
			img.style.height = h + "px";
			img.className = 'image';
			var ptop = (window.getSize().y / 2) + window.getScroll().y - (h/2);
			var pleft = (window.getSize().x / 2) + window.getScroll().x - (w/2);
			var fx = new Fx.Morph(box, {duration: options.duration, transition: options.transition});
			fx.start({
				top: ptop,
				left: pleft,
				width: w,
				height: h,
				opacity: 1
			}).chain(function() {
				if (options.overlay == true) {
					if (!$('imagezoom_overlay')) {
						var overlay = $(document.createElement("div"));
						overlay.setAttribute("id", "imagezoom_overlay");
						overlay.style.backgroundColor = options.overlayColor;
						overlay.setOpacity(0);
						$$('body')[0].appendChild(overlay);
					} else {
						var overlay = $('imagezoom_overlay');
					}
					overlay.style.width = window.getScrollSize().x + "px";
					overlay.style.height = window.getScrollSize().y + "px";
					var overlayfx = new Fx.Morph(overlay, {duration: 600});
					overlayfx.start({
						opacity: options.overlayOpacity
					});
				}
				var close = $(document.createElement("div"));
				close.innerHTML = "<span>" + options.closeText + "</span>";
				close.className = "close";
				close.addEvent("click", function() {
					instance.close(true);
				});
				var loading = box.getElements(".loading");
				if (loading.length > 0)
					box.removeChild(loading[0]);
				var elements = [close, tl, tr, bl, br, top, bottom, left, right, img];
				for (var i = 0; i < elements.length; i++) {
					var elFx = new Fx.Morph(elements[i], {duration: 600});
					elFx.set({opacity: 0});
					box.adopt(elements[i]);
					elFx.start({opacity: 1});
				}
				var caption;
				if ((options.caption != "") && (options.enableCaptions == true)) {
					caption = document.createElement("div");
					caption.className = "caption";
					caption.innerHTML = "<p>" + options.caption + "</p>";
					box.appendChild(caption);
				}
				instance.addSetNavigation();
				if (box.getElements(".caption").length > 0) {
					caption = box.getElements(".caption")[0];
					var cfx = new Fx.Morph(caption, {duration: 200});
					cfx.set({opacity: 0});
					if (options.showCaptionBar == true) {
						caption.className += " visibleCaption";
						var cStartFx = new Fx.Morph(caption, {duration: 600});
						cStartFx.start({
							opacity: 1
						});
					}
					box.addEvent("mouseenter", function() {
						cfx.start({opacity: 1}).chain(function() { caption.className += " visibleCaption"; });
					});
					box.addEvent("mouseleave", function() {
						cfx.start({opacity: 0}).chain(function() { caption.className = caption.className.replace(/visibleCaption/g, ""); });
					});
					close.addEvent("mouseenter", function() {
						cfx.start({opacity: 0}).chain(function() { caption.className = caption.className.replace(/visibleCaption/g, ""); });
					});
					box.getElements(".image")[0].addEvent("click", function() {
						var action = "show";
						if (caption.className.indexOf("visibleCaption") != -1)
							action = "hide";
						if (action == "show")
							cfx.start({opacity: 1}).chain(function() { caption.className += " visibleCaption"; });
						else
							cfx.start({opacity: 0}).chain(function() { caption.className = caption.className.replace(/visibleCaption/g, ""); });
					});				
				}
				top.style.width = box.offsetWidth + "px";
				bottom.style.width = box.offsetWidth + "px";
				left.style.height = box.offsetHeight + "px";
				right.style.height = box.offsetHeight + "px";
				if (options.draggable == true)
					var move = new Drag.Move(box, {handle: img});
			});		
		}
		
		this.addSetNavigation = function() {
			var links = $$(document.links).filter(function(link) {
				if ((link.rel) && (link.rel.indexOf(options.rel) != -1))
					return true;
				else
					return false;
			});
			var set = false;
			for (var i = 0; i < links.length; i++) {
				if ((links[i].href.indexOf(options.image) != -1) && (links[i].rel) && (links[i].rel.indexOf(options.rel + '[' != -1))) {
					var rel = links[i].getAttribute("rel");
					set = instance.scanRel("after", options.rel + "[", this.scanRel("before", "]", rel));
				}
			}
			if (set != false) {
				var prevLink = false;
				var nextLink = false;
				var setLinks = new Array();
				for (i = 0; i < links.length; i++) {
					if (links[i].rel.indexOf(options.rel + "[" + set + "]") != -1) {
						setLinks[setLinks.length] = links[i];
					}
				}
				for (i = 0; i < setLinks.length; i++) {
					var link = setLinks[i];
					if ((link.href.indexOf(options.image) != -1) && (link.rel) && (link.rel.indexOf(options.rel != -1))) {
						if (i != 0)
							prevLink = setLinks[i - 1];
						if (i != setLinks.length - 1)
							nextLink = setLinks[i + 1];
					}
				}
				if ((prevLink != false) || (nextLink != false)) {
					if (box.getElements(".caption").length == 0) {
						var caption = document.createElement("div");
						caption.className = "caption";
						box.appendChild(caption);
					} else {
						var caption = box.getElements(".caption")[0];
					}
				}
				if (prevLink != false) {
					var previousButton = $(document.createElement("div"));
					previousButton.className = "previous";
					var prevCap = '';
					if (prevLink.title)
						prevCap = prevLink.title;
					var prevEl = prevLink;
					if (prevLink.getElements("img").length > 0)
						prevEl = prevLink.getElements("img")[0];
					previousButton.addEvent("click", function() {
						var newOptions = $unlink(options);
						var imagezoomPrev = new Imagezoom($extend(newOptions, {
							image: prevLink.href,
							caption: prevCap,
							rel: options.rel,
							startElement: prevEl,
							showCaptionBar: true
						}));
						instance.close();
						imagezoomPrev.show();
					});
					caption.appendChild(previousButton);
				}
				if (nextLink != false) {
					var nextButton = $(document.createElement("div"));
					nextButton.className = "next";
					var nextCap = '';
					if (nextLink.title)
						nextCap = nextLink.title;
					var nextEl = nextLink;
					if (nextLink.getElements("img").length > 0)
						nextEl = nextLink.getElements("img")[0];
					nextButton.addEvent("click", function() {
						var newOptions = $unlink(options);
						var imagezoomNext = new Imagezoom($extend(newOptions, {
							image: nextLink.href,
							caption: nextCap,
							rel: options.rel,
							startElement: nextEl,
							showCaptionBar: true
						}));
						instance.close();
						imagezoomNext.show();
					});
					caption.appendChild(nextButton);					
				}
			}
		}
		
		this.scanRel = function(where, needle, string) {
			var newstring = '';
			if (where == "after") {
				var startpos = string.indexOf(needle) + needle.length;
				var endpos = string.length;
			} else if (where == "before") {
				var startpos = 0;
				var endpos = string.indexOf(needle);
			}
			for (var i = startpos; i < endpos; i++) {
				newstring += string.charAt(i);
			}
			return newstring;
		}
		
		this.close = function(hideOverlay) {
			var img = box.getElements(".image")[0];
			box.removeChild(img);
			var close = box.getElements(".close")[0];
			box.removeChild(close);
			var caption = box.getElements(".caption");
			if (caption.length > 0)
				box.removeChild(caption[0]);
			var s = box.getElements(".s");
			for (var i = 0; i < s.length; i++)
				box.removeChild(s[i]);
			var x = options.x;
			var y = options.y;
			var boxWidth = options.initWidth;
			var boxHeight = options.initHeight;
			if (options.startElement != false) {
				x = options.startElement.getPosition().x;
				y = options.startElement.getPosition().y;
				boxWidth = options.startElement.offsetWidth;
				boxHeight = options.startElement.offsetHeight;
			}
			if ((hideOverlay == true) && ($('imagezoom_overlay'))) {
				var oFx = new Fx.Morph($('imagezoom_overlay'), {duration: options.closeDuration});
				oFx.start({opacity: 0}).chain(function() {
					$$('body')[0].removeChild($('imagezoom_overlay'));
				});
			}
			var fx = new Fx.Morph(box, {duration: options.closeDuration});
			fx.start({
				left: x,
				top: y,
				width: boxWidth,
				height: boxHeight,
				opacity: options.startOpacity
			}).chain(function() {
				fx.start({
					opacity: 0
				}).chain(function() {
					$$('body')[0].removeChild(box);
				});
			});
		}	
	}
	var UvumiDropdown=new Class({Implements:Options,options:{duration:250,transition:Fx.Transitions.linear},initialize:function(a,b){this.menu=a;this.setOptions(b);window.addEvent('domready',this.domReady.bind(this))},domReady:function(){this.menu=$(this.menu);if(!$defined(this.menu)){return false}if(this.menu.get('tag')!='ul'){this.menu=this.menu.getFirst('ul');if(!$defined(this.menu)){return false}}this.menu.setStyles({overflow:'hidden',height:0,marginLeft:(Browser.Engine.trident?1:-1)});this.createSubmenu(this.menu);this.menu.getChildren('li').setStyles({'float':'left',display:'block',top:0});var a=new Element('li',{html:"&nbsp;",styles:{clear:'both',display:(Browser.Engine.trident?'inline':'block'),position:'relative',top:0,height:0,width:0,fontSize:0,lineHeight:0,margin:0,padding:0}}).inject(this.menu);this.menu.setStyles({height:'auto',overflow:'visible'})},createSubmenu:function(c){var d=c.getChildren('li');var e=0;d.each(function(a){a.setStyles({position:'relative',display:'block',top:-e,zIndex:1});e+=a.getSize().y;var b=a.getFirst('ul');if($defined(b)){b.setStyle('display','none');if(c==this.menu){var x=0;var y=a.getSize().y;this.options.link='cancel';a.store('animation',new Fx.Elements($$(b,b.getChildren('li')).setStyle('opacity',0),this.options))}else{var x=a.getSize().x-a.getStyle('border-left-width').toInt();var y=-a.getStyle('border-bottom-width').toInt();this.options.link='chain';a.store('animation',new Fx.Elements($$(b,b.getChildren('li')).setStyle('opacity',0),this.options));e=a.getSize().y+a.getPosition(this.menu).y}b.setStyles({position:'absolute',display:'block',top:y,left:x,marginLeft:-x,opacity:0});this.createSubmenu(b);a.addEvents({mouseenter:this.showChildList.bind(this,a),mouseleave:this.hideChildList.bind(this,a)}).addClass('submenu')}},this)},showChildList:function(b){var c=b.getFirst('ul');var d=$$(c.getChildren('li'));var e=b.retrieve('animation');if(b.getParent('ul')!=this.menu){e.cancel();e.start({0:{opacity:1,marginLeft:0},1:{opacity:1}});var f={}}else{var f={0:{opacity:1}}}d.each(function(a,i){f[i+1]={top:0,opacity:1}});b.setStyle('z-index',99);e.start(f)},hideChildList:function(b){var c=b.retrieve('animation');var d=b.getFirst('ul');var e=$$(d.getChildren('li'));var f=0;var g={};e.each(function(a,i){g[i+1]={top:-f,opacity:0};f+=a.getSize().y});b.setStyle('z-index',1);if(b.getParent('ul')!=this.menu){g[1]=null;c.cancel();c.start(g);c.start({0:{opacity:0,marginLeft:-d.getSize().x},1:{opacity:0}})}else{g[0]={opacity:0};c.start(g)}}});

/**
 * SqueezeBox - Expandable Lightbox
 *
 * Allows to open various content as modal,
 * centered and animated box.
 *
 * Dependencies: MooTools 1.2
 *
 * Inspired by
 *  ... Lokesh Dhakar	- The original Lightbox v2
 *
 * @version		1.1 rc4
 *
 * @license		MIT-style license
 * @author		Harald Kirschner <mail [at] digitarald.de>
 * @copyright	Author
 */

var SqueezeBox = {

	presets: {
		onOpen: $empty,
		onClose: $empty,
		onUpdate: $empty,
		onResize: $empty,
		onMove: $empty,
		onShow: $empty,
		onHide: $empty,
		size: {x: 600, y: 450},
		sizeLoading: {x: 200, y: 150},
		marginInner: {x: 20, y: 20},
		marginImage: {x: 50, y: 75},
		handler: false,
		target: null,
		closable: true,
		closeBtn: true,
		zIndex: 65555,
		overlayOpacity: 0.7,
		classWindow: '',
		classOverlay: '',
		overlayFx: {},
		resizeFx: {},
		contentFx: {},
		parse: false, // 'rel'
		parseSecure: false,
		shadow: true,
		document: null,
		ajaxOptions: {}
	},

	initialize: function(presets) {
		if (this.options) return this;

		this.presets = $merge(this.presets, presets);
		this.doc = this.presets.document || document;
		this.options = {};
		this.setOptions(this.presets).build();
		this.bound = {
			window: this.reposition.bind(this, [null]),
			scroll: this.checkTarget.bind(this),
			close: this.close.bind(this),
			key: this.onKey.bind(this)
		};
		this.isOpen = this.isLoading = false;
		return this;
	},

	build: function() {
		this.overlay = new Element('div', {
			id: 'sbox-overlay',
			styles: {display: 'none', zIndex: this.options.zIndex}
		});
		this.win = new Element('div', {
			id: 'sbox-window',
			styles: {display: 'none', zIndex: this.options.zIndex + 2}
		});
		if (this.options.shadow) {
			if (Browser.Engine.webkit420) {
				this.win.setStyle('-webkit-box-shadow', '0 0 10px rgba(0, 0, 0, 0.7)');
			} else if (!Browser.Engine.trident4) {
				var shadow = new Element('div', {'class': 'sbox-bg-wrap'}).inject(this.win);
				var relay = function(e) {
					this.overlay.fireEvent('click', [e]);
				}.bind(this);
				['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'].each(function(dir) {
					new Element('div', {'class': 'sbox-bg sbox-bg-' + dir}).inject(shadow).addEvent('click', relay);
				});
			}
		}
		this.content = new Element('div', {id: 'sbox-content'}).inject(this.win);
		this.closeBtn = new Element('a', {id: 'sbox-btn-close', href: '#'}).inject(this.win);
		this.fx = {
			overlay: new Fx.Tween(this.overlay, $merge({
				property: 'opacity',
				onStart: Events.prototype.clearChain,
				duration: 250,
				link: 'cancel'
			}, this.options.overlayFx)).set(0),
			win: new Fx.Morph(this.win, $merge({
				onStart: Events.prototype.clearChain,
				unit: 'px',
				duration: 750,
				transition: Fx.Transitions.Quint.easeOut,
				link: 'cancel',
				unit: 'px'
			}, this.options.resizeFx)),
			content: new Fx.Tween(this.content, $merge({
				property: 'opacity',
				duration: 250,
				link: 'cancel'
			}, this.options.contentFx)).set(0)
		};
		$(this.doc.body).adopt(this.overlay, this.win);
	},

	assign: function(to, options) {
		return ($(to) || $$(to)).addEvent('click', function() {
			return !SqueezeBox.fromElement(this, options);
		});
	},
	
	open: function(subject, options) {
		this.initialize();

		if (this.element != null) this.trash();
		this.element = $(subject) || false;
		
		this.setOptions($merge(this.presets, options || {}));
		
		if (this.element && this.options.parse) {
			var obj = this.element.getProperty(this.options.parse);
			if (obj && (obj = JSON.decode(obj, this.options.parseSecure))) this.setOptions(obj);
		}
		this.url = ((this.element) ? (this.element.get('href')) : subject) || this.options.url || '';

		this.assignOptions();
		
		var handler = handler || this.options.handler;
		if (handler) return this.setContent(handler, this.parsers[handler].call(this, true));
		var ret = false;
		return this.parsers.some(function(parser, key) {
			var content = parser.call(this);
			if (content) {

				ret = this.setContent(key, content);
				return true;
			}
			return false;
		}, this);
	},
	
	fromElement: function(from, options) {
		return this.open(from, options);
	},

	assignOptions: function() {
		this.overlay.set('class', this.options.classOverlay);
		this.win.set('class', this.options.classWindow);
		if (Browser.Engine.trident4) this.win.addClass('sbox-window-ie6');
	},

	close: function(e) {
		var stoppable = ($type(e) == 'event');
		if (stoppable) e.stop();
		if (!this.isOpen || (stoppable && !$lambda(this.options.closable).call(this, e))) return this;
		this.fx.overlay.start(0).chain(this.toggleOverlay.bind(this));
		this.win.setStyle('display', 'none');
		this.fireEvent('onClose', [this.content]);
		this.trash();
		this.toggleListeners();
		this.isOpen = false;
		return this;
	},

	trash: function() {
		this.element = this.asset = null;
		this.content.empty();
		this.options = {};
		this.removeEvents().setOptions(this.presets).callChain();
	},

	onError: function() {
		this.asset = null;
		this.setContent('string', this.options.errorMsg || 'An error occurred');
	},

	setContent: function(handler, content) {
		if (!this.handlers[handler]) return false;
		this.content.className = 'sbox-content-' + handler;
		this.applyTimer = this.applyContent.delay(this.fx.overlay.options.duration, this, this.handlers[handler].call(this, content));
		if (this.overlay.retrieve('opacity')) return this;
		this.toggleOverlay(true);
		this.fx.overlay.start(this.options.overlayOpacity);
		return this.reposition();
	},

	applyContent: function(content, size) {
		if (!this.isOpen && !this.applyTimer) return;
		this.applyTimer = $clear(this.applyTimer);
		this.hideContent();
		if (!content) {
			this.toggleLoading(true);
		} else {
			if (this.isLoading) this.toggleLoading(false);
			this.fireEvent('onUpdate', [this.content], 20);
		}
		if (content) {
			if (['string', 'array'].contains($type(content))) this.content.set('html', content);
			else if (!this.content.hasChild(content)) this.content.adopt(content);
		}
		this.callChain();
		if (!this.isOpen) {
			this.toggleListeners(true);
			this.resize(size, true);
			this.isOpen = true;
			this.fireEvent('onOpen', [this.content]);
		} else {
			this.resize(size);
		}
	},

	resize: function(size, instantly) {
		this.showTimer = $clear(this.showTimer || null);
		var box = this.doc.getSize(), scroll = this.doc.getScroll();
		this.size = $merge((this.isLoading) ? this.options.sizeLoading : this.options.size, size);
		var to = {
			width: this.size.x,
			height: this.size.y,
			left: (scroll.x + (box.x - this.size.x - this.options.marginInner.x) / 2).toInt(),
			top: (scroll.y + (box.y - this.size.y - this.options.marginInner.y) / 2).toInt()
		};
		this.hideContent();
		if (!instantly) {
			this.fx.win.start(to).chain(this.showContent.bind(this));
		} else {
			this.win.setStyles(to).setStyle('display', '');
			this.showTimer = this.showContent.delay(50, this);
		}
		return this.reposition();
	},

	toggleListeners: function(state) {
		var fn = (state) ? 'addEvent' : 'removeEvent';
		this.closeBtn[fn]('click', this.bound.close);
		this.overlay[fn]('click', this.bound.close);
		this.doc[fn]('keydown', this.bound.key)[fn]('mousewheel', this.bound.scroll);
		this.doc.getWindow()[fn]('resize', this.bound.window)[fn]('scroll', this.bound.window);
	},

	toggleLoading: function(state) {
		this.isLoading = state;
		this.win[(state) ? 'addClass' : 'removeClass']('sbox-loading');
		if (state) this.fireEvent('onLoading', [this.win]);
	},

	toggleOverlay: function(state) {
		var full = this.doc.getSize().x;
		this.overlay.setStyle('display', (state) ? '' : 'none');
		this.doc.body[(state) ? 'addClass' : 'removeClass']('body-overlayed');
		if (state) {
			this.scrollOffset = this.doc.getWindow().getSize().x - full;
			this.doc.body.setStyle('margin-right', this.scrollOffset);
		} else {
			this.doc.body.setStyle('margin-right', '');
		}
	},

	showContent: function() {
		if (this.content.get('opacity')) this.fireEvent('onShow', [this.win]);
		this.fx.content.start(1);
	},

	hideContent: function() {
		if (!this.content.get('opacity')) this.fireEvent('onHide', [this.win]);
		this.fx.content.cancel().set(0);
	},

	onKey: function(e) {
		switch (e.key) {
			case 'esc': this.close(e);
			case 'up': case 'down': return false;
		}
	},

	checkTarget: function(e) {
		return this.content.hasChild(e.target);
	},

	reposition: function() {
		var size = this.doc.getSize(), scroll = this.doc.getScroll(), ssize = this.doc.getScrollSize();
		this.overlay.setStyles({
			width: ssize.x + 'px',
			height: ssize.y + 'px'
		});
		this.win.setStyles({
			left: (scroll.x + (size.x - this.win.offsetWidth) / 2 - this.scrollOffset).toInt() + 'px',
			top: (scroll.y + (size.y - this.win.offsetHeight) / 2).toInt() + 'px'
		});
		return this.fireEvent('onMove', [this.overlay, this.win]);
	},

	removeEvents: function(type){
		if (!this.$events) return this;
		if (!type) this.$events = null;
		else if (this.$events[type]) this.$events[type] = null;
		return this;
	},

	extend: function(properties) {
		return $extend(this, properties);
	},

	handlers: new Hash(),

	parsers: new Hash()

};

SqueezeBox.extend(new Events($empty)).extend(new Options($empty)).extend(new Chain($empty));

SqueezeBox.parsers.extend({

	image: function(preset) {
		return (preset || (/\.(?:jpg|png|gif)$/i).test(this.url)) ? this.url : false;
	},

	clone: function(preset) {
		if ($(this.options.target)) return $(this.options.target);
		if (this.element && !this.element.parentNode) return this.element;
		var bits = this.url.match(/#([\w-]+)$/);
		return (bits) ? $(bits[1]) : (preset ? this.element : false);
	},

	ajax: function(preset) {
		return (preset || (this.url && !(/^(?:javascript|#)/i).test(this.url))) ? this.url : false;
	},

	iframe: function(preset) {
		return (preset || this.url) ? this.url : false;
	},

	string: function(preset) {
		return true;
	}
});

SqueezeBox.handlers.extend({

	image: function(url) {
		var size, tmp = new Image();
		this.asset = null;
		tmp.onload = tmp.onabort = tmp.onerror = (function() {
			tmp.onload = tmp.onabort = tmp.onerror = null;
			if (!tmp.width) {
				this.onError.delay(10, this);
				return;
			}
			var box = this.doc.getSize();
			box.x -= this.options.marginImage.x;
			box.y -= this.options.marginImage.y;
			size = {x: tmp.width, y: tmp.height};
			for (var i = 2; i--;) {
				if (size.x > box.x) {
					size.y *= box.x / size.x;
					size.x = box.x;
				} else if (size.y > box.y) {
					size.x *= box.y / size.y;
					size.y = box.y;
				}
			}
			size.x = size.x.toInt();
			size.y = size.y.toInt();
			this.asset = $(tmp);
			tmp = null;
			this.asset.width = size.x;
			this.asset.height = size.y;
			this.applyContent(this.asset, size);
		}).bind(this);
		tmp.src = url;
		if (tmp && tmp.onload && tmp.complete) tmp.onload();
		return (this.asset) ? [this.asset, size] : null;
	},

	clone: function(el) {
		if (el) return el.clone();
		return this.onError();
	},

	adopt: function(el) {
		if (el) return el;
		return this.onError();
	},

	ajax: function(url) {
		var options = this.options.ajaxOptions || {};
		this.asset = new Request.HTML($merge({
			method: 'get',
			evalScripts: false
		}, this.options.ajaxOptions)).addEvents({
			onSuccess: function(resp) {
				this.applyContent(resp);
				if (options.evalScripts !== null && !options.evalScripts) $exec(this.asset.response.javascript);
				this.fireEvent('onAjax', [resp, this.asset]);
				this.asset = null;
			}.bind(this),
			onFailure: this.onError.bind(this)
		});
		this.asset.send.delay(10, this.asset, [{url: url}]);
	},

	iframe: function(url) {
		this.asset = new Element('iframe', $merge({
			src: url,
			frameBorder: 0,
			width: this.options.size.x,
			height: this.options.size.y
		}, this.options.iframeOptions));
		if (this.options.iframePreload) {
			this.asset.addEvent('load', function() {
				this.applyContent(this.asset.setStyle('display', ''));
			}.bind(this));
			this.asset.setStyle('display', 'none').inject(this.content);
			return false;
		}
		return this.asset;
	},

	string: function(str) {
		return str;
	}

});

SqueezeBox.handlers.url = SqueezeBox.handlers.ajax;
SqueezeBox.parsers.url = SqueezeBox.parsers.ajax;
SqueezeBox.parsers.adopt = SqueezeBox.parsers.clone;