

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//		var: Details
//		This Class generates the big, window filling Details Bubble.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




var Details = new Class(
{
	Implements: [Options, Events],
	
	options: 
	{
		startW: 100,
		startH: 100,
		startX: 200,
		startY: 200,
		page: 'fotografie',
		part: 0,
		project: '000008_landleben',
		activeItem: 0,
		normalItemH: 16,
		overItemH: 32,
		downItemH: 10,
		activeItemH: 26,
		zoomed: false,
		playing: true,
		playDelay: 9000,
		playTimeout: $empty.delay(100)
	},
	
	elements: {},
	
	
	initialize: function(options)
	{
		// create and animate wrapper
		this.setOptions(options);
		this.elements.wrapper = new Element( 'div', { 'class':'Details', styles:{ width:this.options.startW, height:this.options.startH, left:this.options.startX, top:this.options.startY }});
		// console.log( this.elements.wrapper);
		var winSize = window.getSize();
		var s = 
		{
			w: Math.round( winSize.x * 0.93),
			h: Math.round( winSize.y * 0.95),
			x: Math.round( winSize.x * 0.05),
			y: Math.round( winSize.y * 0.02),
			duration: 200,
			transition: Fx.Transitions.Sine.easeIn
		};
		var morphSettings = { duration:s.duration, transition:s.transition };
		this.elements.wrapper.set( 'morph', morphSettings);
		this.elements.wrapper.morph({ width:s.w, height:s.h, left:s.x, top:s.y });
		// console.log( s.w+' '+s.h+' '+s.x+' '+s.y);
		
		// return: wrapper ///////////////////////////////////////////////////////////////////////////////////////////////////
		// The whole HTML structure will be returned, with all the important attributes and functions implemented into it. ///
		// So the class can easyly be accessed by $(ID) and the rest of it won't be needed from now on. //////////////////////
		// By default, the HTML structure will be injected into the body. ////////////////////////////////////////////////////
		this.init2.delay( 250, this);
		return this.elements.wrapper.inject( $$('body')[0], 'top' ); 
	},
	
	init2: function()
	{
		// then do all the rest
		var wrapper = this.elements.wrapper;
		this.elements.layer = new Element( 'div', { 'class':'layer', opacity:0.001 }).inject( wrapper);
		this.elements.contWrap = new Element( 'div', { 'class':'contWrap' }).inject( wrapper);
		this.elements.content = new Element( 'div', { 'class':'content' }).inject( this.elements.contWrap ); // .fade('in');
		this.elements.loader = new Element( 'div', { 'class':'loader' }).inject( this.elements.content ).fade('hide').fade('in');
		this.elements.info = new Element( 'div', { 'class':'info' }).inject( this.elements.contWrap ).fade('in');
		this.elements.infoFull = new Element( 'div', { 'class':'infoFull' }).inject( this.elements.contWrap );
		this.elements.tools = new Element( 'div', { 'class':'tools' }).inject( this.elements.contWrap ).fade('hide').fade('in');
		this.elements.secLabel = new Element( 'label', { text:' sec ', title:s.labels[26], style:'display:none' }).inject( this.elements.tools);
		this.elements.sec = new Element( 'input', { type:'text', name:'sec', value:this.options.playDelay/1000 }).inject( this.elements.secLabel, 'top');
		this.elements.btnPlay = new Element( 'img', { src:s.baseDir+'style/btn_play.png', title:s.labels[20], style:'display:none' }).inject( this.elements.tools );
		this.elements.btnPause = new Element( 'img', { src:s.baseDir+'style/btn_pause.png', title:s.labels[21], style:'display:none' }).inject( this.elements.tools );
		this.elements.btnPlus = new Element( 'img', { src:s.baseDir+'style/btn_plus.png', title:s.labels[22], style:'display:none' }).inject( this.elements.tools );
		this.elements.btnMinus = new Element( 'img', { src:s.baseDir+'style/btn_minus.png', title:s.labels[23], style:'display:none' }).inject( this.elements.tools );
		this.elements.btnDownloadAll = new Element( 'img', { src:s.baseDir+'style/btn_download_all.png', title:s.labels[12], style:'display:none' }).inject( this.elements.tools );
		this.elements.btnDownload = new Element( 'img', { src:s.baseDir+'style/btn_download.png', title:s.labels[13], style:'display:none' }).inject( this.elements.tools );
		this.elements.btnClose = new Element( 'img', { src:s.baseDir+'style/btn_close.png', title:s.labels[14] }).inject( this.elements.tools );
		this.elements.btnClose.addEvent( 'click', function() { window.location.href = '#'+this.options.part; }.bind(this));
		this.elements.footer = new Element( 'div', { 'class':'footer' }).inject( this.elements.contWrap ).fade('hide').fade('in');
		this.elements.items = new Element( 'div', { 'class':'items' }).inject( this.elements.footer ).fade('hide');
		this.elements.btnPrev = new Element( 'img', { 'class':'btnPrev', src:s.baseDir+'style/btn_prev.png', title:s.labels[16] }).inject( this.elements.footer );
		this.elements.btnNext = new Element( 'img', { 'class':'btnNext', src:s.baseDir+'style/btn_next.png', title:s.labels[15] }).inject( this.elements.footer );

		$('Preloader').preload( s.baseDir+'style/btn_play_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_play_down.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_pause_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_pause_down.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_prev_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_prev_down.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_next_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_next_down.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_plus_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_plus_down.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_minus_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_minus_down.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_download_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_download_down.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_download_all_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_download_all_down.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_close_over.png', 2 );
		$('Preloader').preload( s.baseDir+'style/btn_close_down.png', 2 );



		// var: extensions ///////////////////////////////////////////////////////////////////////////////////////////////////
		// This in fact is the *real* class. All important functionality will be implemented into the HTML wrapper DIV for easy access by $(ID).
		
		var extensions = 
		{
			options: this.options,
			elements: this.elements,


			// func: activate
			// Retrieve JSON data, build the navigation and activate Buttons. This function is called by <ControlCenter>, because it needs to
			// calculate dimensions, and this needs the HTML structure to be injected already. 
			activate: function()
			{
				// Rollovers are depending on the opacity of the buttons.
				var btns = [this.elements.btnPlay, this.elements.btnPause, this.elements.btnPlus, this.elements.btnMinus, this.elements.btnDownload, this.elements.btnDownloadAll, this.elements.btnClose, this.elements.btnPrev, this.elements.btnNext];
				btns.each( function(num)
				{
					num.setStyle('cursor','pointer');
					num.addEvent( 'mouseover', function() { num.set( 'src', num.get('src').replace(/\.png$/,'_over.png')); });
					num.addEvent( 'mouseout', function() { num.set( 'src', num.get('src').replace(/_over\.png$/,'.png').replace(/_down\.png$/,'.png')); });
					num.addEvent( 'mousedown', function() { num.set( 'src', num.get('src').replace(/_over\.png$/,'_down.png')); });
					num.addEvent( 'mouseup', function() { num.set( 'src', num.get('src').replace(/_down\.png$/,'_over.png')); });
				});
				
				// Switch to previous or next image.
				this.elements.btnNext.addEvent( 'click', this.nextItem.bind(this));
				this.elements.btnPrev.addEvent( 'click', this.prevItem.bind(this));
				
				// Zoom
				this.elements.btnPlus.addEvent( 'click', this.zoomImage.bind(this));
				this.elements.btnMinus.addEvent( 'click', function() 
				{
					this.options.zoomed = false; 
					this.fitImage('morph'); 
					this.elements.btnPlus.setStyle('display','inline'); 
					this.elements.btnMinus.setStyle('display','none'); 
				}.bind(this));
				
				// Play
				this.elements.btnPlay.addEvent( 'click', function() 
				{
					this.options.playing = true;
					this.options.playTimeout = this.nextItem.delay( this.options.playDelay/4, this);
					this.elements.btnPause.setStyle('display','inline'); 
					this.elements.secLabel.setStyle('display','inline');
					this.elements.btnPlay.setStyle('display','none'); 
				}.bind(this));
				this.elements.btnPause.addEvent( 'click', function() 
				{
					this.options.playing = false;
					$clear( this.options.playTimeout);
					this.elements.btnPause.setStyle('display','none'); 
					this.elements.secLabel.setStyle('display','none');
					this.elements.btnPlay.setStyle('display','inline'); 
				}.bind(this));
				
				// set play delay
				this.elements.sec.addEvent( 'keypress', function(ev)
				{
					var allowed = ['1','2','3','4','5','6','7','8','9','0','backspace','delete','left','right','up','down','tab'];
					if( allowed.indexOf(ev.key)==-1) ev.stop();
					if( ev.key=='enter') this.elements.sec.blur();
				}.bind(this));
				this.elements.sec.addEvent( 'change', function()
				{
					if( this.elements.sec.get('value').toInt()<1)  this.elements.sec.set( 'value', '1');
					this.options.playDelay = this.elements.sec.get('value').toInt() * 1000;
					this.managePlaying();
				}.bind(this));
							
				// First time, the loading animation will fade in slowly.
				this.elements.loader.set( 'tween', { duration:3000 });
				this.elements.loader.fade('in');
				
				// Retrieve JSON data and customize the Details bubble.
				var req = new Request( 
				{
					url: s.baseDir+'data/_json/'+s.lang+'_'+s.page+'_'+this.options.project+'.json?'+new Date().getTime(),
					method: 'get',
					onFailure: function(error) { alert('Failure!'); },
					onException: function(headerName, value) { alert('Exception!'); },
					onSuccess: function(responseText)
					{
						this.options.jsonData = JSON.decode(responseText);
						
						// Activate title and download-buttons
						this.options.title = this.options.jsonData.title;
						this.elements.info.set( 'html', this.options.title );
						if( this.options.jsonData.download) 
						{
							this.elements.btnDownloadAll.setStyle('display','inline');
							this.elements.btnDownloadAll.addEvent('click', function() 
							{
								window.location.href = this.options.jsonData.download; 
							}.bind(this));
						}
						else this.elements.btnDownloadAll.setStyle('display','none');
						this.elements.btnDownload.addEvent('click', function()
						{
							if( this.options.downloadItem )
							{
								window.location.href = this.options.downloadItem; 
							}							
						}.bind(this));
						
						// If more than one item, 
						if( this.options.jsonData.slides.length > 1)
						{
							// show arrows
							this.elements.btnPrev.fade('in');
							this.elements.btnNext.fade('in');
							this.elements.items.fade('in');
							
							// and build up items-navigation. 
							new Element( 'img', { src:s.baseDir+'style/spacer.gif', styles:{ width:'1px', height:this.options.overItemH+'px' }}).inject( this.elements.items );
							this.options.jsonData.slides.each( function(num, i)
							{
								var a = new Element( 'a', { href:'#'+this.options.project+'/'+i+'/', html:'<img class="pin" src="'+s.baseDir+'style/spacer.gif" />' }).inject( this.elements.items );
								if( num.S )
								{
									var src = s.baseDir+num.S;
									//  console.log( src);
									$('Preloader').preload.delay( 1000, $('Preloader'), [ s.baseDir+num.S, 8 ]);
									$('Preloader').addEvent( 'complete', function(file) 
									{
										// console.log( file); 
										if( file==src && !a.getElements('img.thumb')[0]) 
										{
											new Element( 'img', { src:src, 'class':'thumb' }).inject( a );
										}
									}.bind(this));
								}
								a.getChildren()[0].set( 'morph', { duration:1000, transition:Fx.Transitions.Cubic.easeOut });
								var mouseover = 0;
								a.addEvent( 'mouseover', function() 
								{
									mouseover = 1; 
									if( !a.hasClass('active'))
									{
										a.getChildren()[0].setStyles({ height:this.options.overItemH, backgroundColor:'#ff0000' }); 
										a.getElements('img.thumb').fade('show');
									}
								}.bind(this));
								a.addEvent( 'mouseout', function() 
								{
									mouseover = 0; 
									function mouseoutHandler() 
									{
										if( !a.hasClass('active') && mouseover==0) a.getChildren()[0].morph({ height:this.options.normalItemH, backgroundColor:'#ffffff' }); 
										if( mouseover==0) a.getElements('img.thumb').fade('out');
									}
									mouseoutHandler.delay(10,this);
								}.bind(this));
								a.addEvent( 'mousedown', function()
								{
									if( !a.hasClass('active')) a.getChildren()[0].setStyles({ height:this.options.downItemH }); 
									a.getElements('img.thumb').fade('out');
								}.bind(this));
								a.addEvent( 'mouseup', function()
								{
									if( !a.hasClass('active')) a.getChildren()[0].setStyles({ height:this.options.activeItemH }); 
								}.bind(this));
							}, this);							
						}
						else
						{
							// Else hide arrows and item-nav and resize the contentarea is by <resize>.
							this.elements.btnPrev.setStyle('display','none');
							this.elements.btnNext.setStyle('display','none');
							this.elements.items.setStyle('display','none');
							this.resize();
						}
						// Repeat the <showItem> call, that had been made by <ControlCenter> before the jsonData has been available. 
						this.showItem( this.options.activeItem );
					}.bind(this)
				}).send();
			},
			
			
			// func: showItem
			// Shows the desired item, if avaliable. If not, shows the first item. Normally this function is called by the <ControlCenter>. 
			showItem: function()
			{
				$clear( this.options.playTimeout);
				
				// But if the JSON data isn't present already, the function call will be repeated by <activate>. 
				if( this.options.jsonData )
				{
					// First of all, tries to apply the number given as argument. If none, zero. 
					if( $A(arguments)[0] ) this.options.activeItem = Number( $A(arguments)[0]); 
					else this.options.activeItem = 0;
					
					// Then update the items-navigation on the bottom
					this.elements.items.getElements('a').each( function(num, i)
					{
						if( i==this.options.activeItem) 
						{
							num.addClass('active'); 
							num.getChildren()[0].setStyles({ height:this.options.activeItemH }).morph({ backgroundColor:'#ffffff' });
						}
						else
						{
							num.removeClass('active');
							num.getChildren()[0].setStyles({ height:this.options.normalItemH, backgroundColor:'#ffffff' });
						}
					},this);
					$clear(this.updateItemsDelay);
					this.updateItemsDelay = this.updateItems.delay(1000, this);
					
					// And, of course, change the displayed content by removing the previous elements,
					this.elements.content.getChildren().each( function(num)
					{
						if( !num.hasClass('loader'))
						{
							num.set('tween', { duration:200 }).fade('out');
							function disappear(what) { what.destroy(); }
							disappear.delay(200, this, num);
						}
					},this);
					
					// applying an image-title if present 
					var newItem = this.options.jsonData.slides[ this.options.activeItem ];
					if( newItem.text ) 
					{
						// console.log( newItem.title.length );
						if( newItem.text.length >130 )
						{
							this.elements.info.set('html', '');
							this.elements.infoFull.set('html', newItem.text );
							this.elements.infoFull.setStyle('display','block');
						}
						else
						{
							this.elements.info.set('html', newItem.text );
							this.elements.infoFull.setStyle('display','none');
						}
					}
					else 
					{
						this.elements.info.set('html', this.options.title);
						this.elements.infoFull.setStyle('display','none');
					}
					
					// calling <showImage>, <showWebSite>, <showFLV> or <showMP3>,
					if( newItem.L.test(/\.jpg$/) || newItem.L.test(/\.gif$/) || newItem.L.test(/\.png$/)) this.showImage(newItem.L, newItem.Lw, newItem.Lh);
					else if( newItem.L.test(/\.htm$/) || newItem.L.test(/\.php$/) || newItem.L.test(/\.swf$/) || newItem.L.test(/\.pdf$/)) this.showIFrame(newItem.L);
					else if( newItem.L.test(/\.flv$/)) this.showFLV(newItem.L);
					else if( newItem.L.test(/\.mp3$/)) this.showMP3(newItem.L);
					
					// preloading the next image
					if( this.options.jsonData.slides[ this.options.activeItem +1 ] ) 
					{
						var nextItem = this.options.jsonData.slides[ this.options.activeItem +1 ];
						if( nextItem.L.test(/\.jpg$/) || nextItem.L.test(/\.gif$/) || nextItem.L.test(/\.png$/)) $('Preloader').preload.delay( 1000, $('Preloader'), [ s.baseDir+nextItem.L, 3 ]);
					}
					
					// and de/activating the download button.
					if( newItem.XL ) 
					{
						this.elements.btnDownload.setStyle('display','inline');
						if( newItem.XL.test(/\.jpg$/) || newItem.XL.test(/\.png$/) || newItem.XL.test(/\.gif$/) || newItem.XL.test(/\.pdf$/))
						{
							var filepath = newItem.XL;
							var filename = filepath.split('/'); filename = filename[ filename.length-1 ];
							this.options.downloadItem = s.baseDir+'download.php?filename='+filename+'&filepath='+filepath; 
						}
						else this.options.downloadItem = newItem.XL;
					}
					else
					{
						this.elements.btnDownload.setStyle('display','none');
						this.options.downloadItem = '';
					}	
					
					// If it lasts some time, start loader animation.
					var showLoader = function() { if( this.elements) this.elements.loader.set( 'tween', { duration:1000 }).fade('in'); }.bind(this);
					this.options.loaderTimeout = showLoader.delay(900, this);
				}
			},
			
			
			// func: updateItems
			// keeps the itemNav fitting into the items box. updates the items nav on <showItem> and on window resize
			updateItemsDelay: $empty.delay(100),
			updateItems: function()
			{
				var itemW = 5;
				var boxW = this.elements.items.getSize().x - 10;
				var firstVisible = 0;
				var lastVisible = Math.floor(boxW/itemW);
				var itemsLength = this.elements.items.getElements('a').length;
				if( itemsLength >lastVisible)
				{
					firstVisible = this.options.activeItem - Math.floor(lastVisible/2);
					lastVisible = this.options.activeItem + Math.floor(lastVisible/2)-1;
					if( firstVisible<0) lastVisible -= firstVisible;
					if( lastVisible>itemsLength) firstVisible -= lastVisible-itemsLength;
				}
				this.elements.items.getElements('a').each( function(num, i)
				{
					if( i<firstVisible || i>lastVisible) num.setStyle('display','none'); 
					else num.setStyle('display','inline').fade('show'); 
				},this);
			},
			
			
			// func: showImage
			// Realizes displaying JPGs, GIFs and PNGs as a sliding fading Layer. 
			showImage: function(file, w, h)
			{
				$('Preloader').preload( s.baseDir+file, 1 );
				var img = new Element( 'img', { src:s.baseDir+file, width:w, height:h }).set('opacity',0.001).inject( this.elements.content );
				this.options.zoomed = false;
				img.addEvent( 'load', function() 
				{
					this.fitImage(); 
					img.set('tween',{duration:200}).fade('in');
					$clear( this.options.loaderTimeout);
					this.elements.loader.set( 'tween', { duration:200 }).fade('out');
				}.bind(this));
				img.addEvent( 'click', function()
				{
					if( !this.options.zoomed) this.zoomImage();
					if( this.options.playing)
					{
						$clear( this.options.playTimeout);
						this.options.playTimeout = this.nextItem.delay( this.options.playDelay, this);
					}
				}.bind(this));
				img.addEvent( 'mousedown', function()
				{
					$clear( this.options.playTimeout);
				}.bind(this));
				img.addEvent( 'mouseup', function()
				{
					if( this.options.playing)
					{
						$clear( this.options.playTimeout);
						this.options.playTimeout = this.nextItem.delay( this.options.playDelay, this);
					}
				}.bind(this));
				
				// set btns and do the playing
				this.elements.btnPlus.setStyle('display','inline');
				this.elements.btnMinus.setStyle('display','none');
				if( this.options.jsonData.slides.length >1)
				{
					if( this.options.playing)
					{
						img.addEvent( 'load', function() { this.managePlaying(); }.bind(this));
						this.elements.btnPlay.setStyle('display','none');
						this.elements.btnPause.setStyle('display','inline');
						this.elements.secLabel.setStyle('display','inline');
					}
					else
					{
						this.elements.btnPlay.setStyle('display','inline');
						this.elements.btnPause.setStyle('display','none');
						this.elements.secLabel.setStyle('display','none');
					}
				}
			},
			
			
			// func: managePlaying
			// set the play timeout
			managePlaying: function()
			{
				$clear( this.options.playTimeout);
				if( this.options.playing) this.options.playTimeout = this.nextItem.delay( this.options.playDelay, this);
			},
			
			
			// func: fitImage
			// Resizes the images inside the contentbox to default view, and de/activates the zoom buttons. Is called by <showImage> and <resize>.
			fitImage: function()
			{
				// console.log( 'Details.fitImage()' );
				$clear( this.blinkTimeout );
				var morph = ''; 
				if( $A(arguments)[0] ) morph = $A(arguments)[0];
				this.elements.content.getElements('img').each( function(num)
				{
					var i, w, h, x, y;
					var c = this.elements.content.getSize();
					num.store('contentSize',c);
					if( num.retrieve('origSize')) 
					{
						i = num.retrieve('origSize');
						// console.log( 'size from element storage: '+i.x+' '+i.y );
					}
					else 
					{
						i = num.getSize(); 
						if( i.x > 0 && i.y > 0 ) num.store('origSize', i); 
						// console.log( 'size from content image: '+i.x+' '+i.y );
					}
					
					// calculate size and position
					var widthWorse = false;
					if( c.x-i.x < c.y-i.y ) widthWorse = true;
					if( widthWorse!=this.options.zoomed)
					{
						// fit width into the contentbox and center height,
						w = c.x;
						h = Math.round(w * i.y/i.x);
						x = 0;
						y = Math.round((c.y - h) /2);
					}
					else
					{
						// else fit height and center width.
						h = c.y;
						w = Math.round(h * i.x/i.y);
						y = 0;
						x = Math.round((c.x - w) /2);
					}
					
					// image cursor, title and dragging
					if( num.retrieve('drag')) { num.retrieve('drag').detach().stop(); }
					if( this.options.zoomed)
					{
						num.set('title','Bild bewegen').setStyle('cursor','move');
						var limX1 = - ( w - c.x);
						var limX2 = 0; 
						var limY1 = - ( h - c.y);
						var limY2 = 0; 
						var drag = new Drag( num, { limit:{ x:[limX1,limX2], y:[limY1,limY2] }});
						num.store('drag',drag);
					}
					else num.set('title','Bild vergrößern').setStyle('cursor','pointer');
					
					// Positions are being applied.
					if( w>0 && h>0 ) 
					{
						if( morph ) num.morph({ width:w, height:h, left:x, top:y });
						else num.setStyles({ width:w, height:h, left:x, top:y });
					}					
				},this);
			},
			

			// func: zoomImage
			// Zooms the image to fill-window-size. for zoom-out see <activate>. 
			zoomImage: function()
			{
				this.options.zoomed = true; 
				this.fitImage('morph'); 
				this.elements.btnPlus.setStyle('display','none'); 
				this.elements.btnMinus.setStyle('display','inline'); 
			},

			
			// func: showWebSite
			// Realizes displaying PHP, HTML, SWF, and PDF files in an iFrame. External WebSites are realized by header-redirections. 
			showIFrame: function(file)
			{
				var iFrame = new Element( 'iframe', { src:s.baseDir+file, frameborder:0 }).set('opacity',0).inject( this.elements.content ).fade('in');
				this.elements.btnPlus.setStyle('display','none');
				this.elements.btnMinus.setStyle('display','none');
				if( this.options.jsonData.slides.length >1)
				{
					if( this.options.playing)
					{
						iFrame.addEvent( 'load', function() { this.managePlaying() }.bind(this));
						this.elements.btnPlay.setStyle('display','none');
						this.elements.btnPause.setStyle('display','inline');
						this.elements.secLabel.setStyle('display','inline');
					}
					else
					{
						this.elements.btnPlay.setStyle('display','inline');
						this.elements.btnPause.setStyle('display','none');
						this.elements.secLabel.setStyle('display','none');
					}
				}
			},
			
			
			// func: showFLV
			// Realizes displaying FLV videos in an iFrame with a flash video player.
			showFLV: function(file)
			{
				var iFrame = new Element( 'iframe', { src:s.baseDir+'VideoPlayer.swf?flv=' + file  }).set('opacity',0).inject( this.elements.content ).fade('in');
				this.elements.btnPlus.setStyle('display','none');
				this.elements.btnMinus.setStyle('display','none');
				this.elements.btnPlay.setStyle('display','none');
				this.elements.btnPause.setStyle('display','none');
				this.elements.secLabel.setStyle('display','none');
			},
			
			
			// func: showMP3
			// Realizes displaying MP3s in an iFrame with a flash audio player.
			showMP3: function(file)
			{
								
			},
			

			// func: resize
			// Fits the <Details> bubble into the window. Is called by a window.resize event handler. 
			resize: function()
			{
				var winSize = window.getSize();
				var s = 
				{
					w: Math.round( winSize.x * 0.93),
					h: Math.round( winSize.y * 0.95),
					x: Math.round( winSize.x * 0.05),
					y: Math.round( winSize.y * 0.02),
					duration: 200,
					transition: Fx.Transitions.Sine.easeIn
				};
				if( $A(arguments).length!=0 ) $extend( s, $A(arguments)[0] );
				var morphSettings = { duration:s.duration, transition:s.transition };
				
				// Resize Layer
				this.elements.layer.set( 'morph', morphSettings);
				this.elements.layer.morph({ width:winSize.x, height:winSize.y, left:-s.x, top:-s.y });
				
				// Resize Wrapper. 
				this.set( 'morph', morphSettings);
				this.morph({ width:s.w, height:s.h, left:s.x, top:s.y });
				
				// Resize the content element accordingly. 
				var contentH = s.h -65;
				if( this.options.jsonData && this.options.jsonData.slides.length <2 ) contentH = s.h -35;
				this.elements.content.set( 'morph', morphSettings);
				this.elements.content.morph({ height:contentH });
				this.fitImage.delay( s.duration, this);
				this.fitImage.delay( s.duration*2, this);
				
				// and of course, resize the items nav
				this.updateItems.delay(300, this);
				return this;
			},
			
			
			// func: prevItem
			// Switches to the previous item.
			prevItem: function()
			{
				if( this.options.activeItem > 0) this.options.activeItem = Number(this.options.activeItem) -1;
				else this.options.activeItem = this.options.jsonData.slides.length -1; 
				window.location.hash = '#'+this.options.project+'/'+this.options.activeItem+'/';
			},
			
			
			// func: nextItem
			// Switches to the next item.
			nextItem: function()
			{
				// console.log( 'Details.nextItem() '+this.options.activeItem );
				if( this.options.activeItem < this.options.jsonData.slides.length -1) this.options.activeItem = Number(this.options.activeItem) +1;
				else this.options.activeItem = 0; 
				window.location.hash = '#'+this.options.project+'/'+this.options.activeItem+'/';
			},
						
			
			// func: disappear
			// Makes the <Details> bubble fade out and self-destroy. Is called by <ControlCenter>. 
			disappear: function()
			{
				console.log( 'Details.disappear()' );
				this.options.playing = false;
				$clear( this.options.playTimeout);
				this.getChildren().each( function(num) { num.fade('hide'); });
				this.set( 'morph', { duration:200, transition:Fx.Transitions.Sine.easeOut });
				this.morph({ left:this.options.startX, top:this.options.startY, width:this.options.startW, height:this.options.startH });
				var destroyDetails = function() { this.destroy(); }.bind(this);
				destroyDetails.delay(200);
			}
			
			
		};
		$extend( wrapper, extensions );
		window.addEvent( 'resize', function() { wrapper.resize(); });
		wrapper.resize();
		wrapper.activate();
		
	}	
});
