/*============================================================================
The Gallery

Version:	1.0.0

Javascript used by The Gallery. Includes support for Ajax requests, slideshow
animation, and browsing through images


Maintainability tasks:

TODO: Replace phaseXXX with phase='show'
=============================================================================*/


// Frontend Snippet folder location
var _base = 'assets/snippets/theGallery/';


/*============================================================================
Data variables
=============================================================================*/

// has 'state' been initialized?
var initialized = false;

/*----------------------------------------------------------------------------
Slideshow variables
----------------------------------------------------------------------------*/

// Image info
var imageIx = 0;
var imageCount = 0;
var filenameArray = new Array();
var titleArray = new Array();
var imageArray = new Array();
var tag = '';

// Preloading
var preloadSubDirs = new Array();
var preloadSetIx = 0;

var preloadSubDir = '';
var preloadIx = 0;

var preloadInit = true;
var preloadInitLimits = new Array();
var preloadWeights = new Array( 1, 10 );
var preloadCount = 0;

var preloadImageObj;

// Viewing div id
var imageStore = '';
var slideSubDir = '';
var thumbSubDir = '';
var viewerId = '';

// Slideshow event timer
var playTimer;
var restartTimer;

// Number of ticks (20ms) for phases defaults
var fadeTicks = 30;
var showTicks = 150;

// Doing slideshow? Slideshow phase?
// Transition?
// - fadeInOut uses FadeIn and FadeOut
// - fadeDirect uses Direct
var slideshow = false;
var play = false;
var phaseFadeOut = false;
var phaseFadeIn = false;
var phaseDirect = false;
var phaseShow = false;
var transition = 'fadeDirect';
var autoStart = false;
var autoStartIndex = 0;

// Current tick
var phaseTick = 0;

// Filmstrip
var stripIx = 0;

// Captions?
var showCaptions = true;

// Tag list - sometimes need to defer update via timer
var tagListTimer;
var tagListTimerCount = 0;

// slidey things
var sliderGalleryControls;
var sliderMiniControls;
var sliderProgressBar;

// timer used to ensure progress bar is slide out as sometimes it gets stuck
var timerSweeper;


/*============================================================================
Initialization
=============================================================================*/

/*----------------------------------------------------------------------------
init

Perform common initialization for all views etc - pass in data and preload
images
- tag				tag selection, if any
- viewerId			id of div that we are displaying in (for AJAX updates)
- tagList			are we also display tagList?
- count				how many images
- filenameArray		image info
- titleArray		image titles
- preloadSubDirs	which image sizes are going to be used ... preload them
- preDisplayCounts	how many of each preloadSubDir to load BEFORE displaying
					anything, or doing autoStart.
- slideSubDir		the primary image size for this view
----------------------------------------------------------------------------*/
function init( tagIn, viewerIdIn, tagList, count, filenameArrayIn, titleArrayIn, imageDir, preloadSubDirsIn, preDisplayCountsIn, slideSubDirIn )
{
	trace('init: '+tagIn);
	
	initialized = true;
	
	tag = tagIn;
	
	// sync tag list
	trace('tagList: ' + tagList);
	if ( tagList )
	{
		updateTagList(tag);
	}
	
	// reset index to start for this data set
	imageIx = 0;
	stripIx = 0;
	
	imageCount = count;
	filenameArray = filenameArrayIn;
	titleArray = titleArrayIn;
	
	preloadImageObj = new Image();
	preloadSubDirs = preloadSubDirsIn;
	preloadInitLimits = preDisplayCountsIn;
	
	imageStore = imageDir;
	slideSubDir = slideSubDirIn;
	viewerId = viewerIdIn;	
	
	preloadInit = true;
	preloadCount = 0;
	
	if ( imageCount > 0 )
	{
		preloadImages();
		
		showControl('galleryProgress');
		
		sliderProgressBar = new Fx.Slide('galleryProgress');
		sliderProgressBar.setOptions( {duration: 1000} );
		sliderProgressBar.hide().slideIn('vertical');
	}
	else
	{
		trace('NO IMAGES');
		
		hideControl('galleryProgress');
	}
}


/*----------------------------------------------------------------------------
initSlideShow

Perform initialization specifically for when slideshow functionality has
been enabled
- thumbSubDir		where are the thumbnails for filmstrip held?
- tranisition		what transition to use
- showTime			how long to show each image (ms)
- fadeTime			how
- autoStart			should slideshow autostart
----------------------------------------------------------------------------*/
function initSlideShow( thumbSubDirIn, transitionIn, showTime, fadeTime, autoStartIn, autoStartIndexIn )
{	
	trace('initSlideShow: thumbSubDirIn='+thumbSubDirIn+' autoStart='+autoStartIn);

	thumbSubDir = thumbSubDirIn;
	
	slideshow = true;
	transition = transitionIn;
	autoStart = autoStartIn;
	autoStartIndex = autoStartIndexIn;
	trace('autoStart: '+autoStart+'/'+autoStartIndex);
	
	// convert time in milliseconds to ticks
	if ( showTime > 0 )
	{
		showTicks = Math.floor(showTime / 20);
	}
	if ( fadeTime > 0 )
	{
		fadeTicks = Math.floor(fadeTime / 20);
	}
	trace('showTime: '+showTime+', showTicks: '+showTicks+', fadeTime: '+fadeTime+', fadeTicks: '+fadeTicks); 
	
	updateControls();
	updateButtons();
}


/*============================================================================
Event Handlers

For user interaction
=============================================================================*/

/*----------------------------------------------------------------------------
onChangeTag

Handle user selecting a tag in tag view - to show the selected tag's images
we need to regenerate the gallery view so initiate an Ajax call to the 
gallery to do just that.
----------------------------------------------------------------------------*/
function onChangeTag(tag)
{
	trace('onChangeTag:');
	trace('- argAutoStart: ' + argAutoStart);
	trace('- argShowTime: '  + argShowTime);
	try
	{
		ajaxGallery( 
			'viewerGallery', 
			false, 
			'gallery', 
			tag, 
			null, 
			null, 
			null, 
			null, 
			true, 
			null, 
			null, 
			null, 
			false 
			);
	}
	catch (ex)
	{
		reportException(ex);
	}
}

/*----------------------------------------------------------------------------
onSelectImage

User clicked on a thumbnail image in the filmstrip. Calculate the image's
index taking into account which group of images the filmstrip is showing.
Then show that image in the main view (unless playing slideshow).
----------------------------------------------------------------------------*/
function onSelectImage(thumbIx)
{
	try
	{
		selectIx = stripIx + thumbIx;
		
		imageIx = selectIx;
		
		if ( !play )
		{
			showSlide();
		}
	}
	catch (ex)
	{
		reportException(ex);
	}
}

/*----------------------------------------------------------------------------
onStartStop

User pressed start/stop button for the slideshow - either in the tag control
panel for the gallery view, or mini view control bar.
----------------------------------------------------------------------------*/
function onStartStop()
{
	try
	{	
		trace('transition: '+transition);
		
		// if already showing slideshow then stop
		if ( play )
		{
			// stop slideshow
			play = false;
			clearTimeout(playTimer);
			
			// clear any fade on current image
			fadeImage(1);
		}
		// else, start the show
		else
		{
			// start slideshow
			play = true;
			
			// init phases
			switch ( transition )
			{
				case 'fadeInOut':
					phaseFadeOut	= false;
					phaseShow		= true;
					phaseFadeIn		= false;
					break;
				case 'fadeDirect':
					phaseDirect		= false;
					phaseShow		= true;
					break;
			}
			
			// make sure next slide is ready
			preloadNextSlide();
			
			// reset to current tick
			phaseTick		= 0;
			
			// and go
			showNextStep();
		}
		
		updateButtons();
		updateControls();
	}
	catch (ex)
	{
		reportException(ex);
	}
}

/*----------------------------------------------------------------------------
onPrev

User pressed prev button in slideshow controls. Only update if not doing
slideshow
----------------------------------------------------------------------------*/
function onPrev()
{
	try
	{
		if ( !play )
		{
			prevSlide();
			
			updateControls();
		}
	}
	catch (ex)
	{
		reportException(ex);
	}
}

/*----------------------------------------------------------------------------
onNext

User pressed next button. Only update if not in slideshow.
----------------------------------------------------------------------------*/
function onNext()
{
	try
	{
		if ( !play )
		{
			nextSlide( false );
			
			updateControls();
		}
	}
	catch (ex)
	{
		reportException(ex);
	}
}

/*----------------------------------------------------------------------------
onPrevGroup

User presed prev group button. Do not update if running slideshow
----------------------------------------------------------------------------*/
function onPrevGroup()
{
	try
	{
		if ( !play )
		{
			if ( stripIx > 0 )
			{
				stripIx = stripIx - 8;
				showThumbs();
			}
		
			updateControls();
		}
	}
	catch (ex)
	{
		reportException(ex);
	}
}

/*----------------------------------------------------------------------------
onNextGroup

User pressed next group button. Do not update if running slideshow
----------------------------------------------------------------------------*/
function onNextGroup()
{
	try
	{
		if ( !play )
		{
			if ( (stripIx+8) < imageCount )
			{
				stripIx = stripIx + 8;
				showThumbs();
			}
			
			updateControls();
		}
	}
	catch (ex)
	{
		reportException(ex);
	}
}

/*----------------------------------------------------------------------------
onCaptions

User pressed captions button. Toggle state of button and whether captions
are being displayed.
----------------------------------------------------------------------------*/
function onCaptions()
{
	try
	{
		// toggle
		showCaptions = !showCaptions;
		
		// captions button
		updateButtons();
	}
	catch (ex)
	{
		reportException(ex);
	}
}


/*============================================================================
Image preloading

The call to init() specifies one or subdirectories of the imageStore from
which we need to load up images. These are refered to as 'sets' below.

Also, preloading is handled in two phases. The first phase preloads the
images that are required to complete the initial display of the view in use
e.g. for photo gallery, we need 1 image for the primary view and 8 for the
filmstrip. The number of images to preload from each set (subdir) is
specified in the init() call too and held in preloadInitLimits.
=============================================================================*/

/*----------------------------------------------------------------------------
preloadImages

Start (or continue) preloading of images, starting with the first set (subdir)
----------------------------------------------------------------------------*/
function preloadImages()
{
	trace('preloadImages ' + preloadSubDirs.length);
	
	if ( preloadSubDirs.length > 0 )
	{
		preloadSetIx = 0;
	
		preloadSet();
	}
}

/*----------------------------------------------------------------------------
preloadSet

For this set, if in first phase (preloadInit) then start at 0, otherwise
continue from the 'init limit'. Initiate preloading of images by calling
preloadImage.
----------------------------------------------------------------------------*/
function preloadSet()
{
	trace('preloadSet: '+preloadSetIx+','+preloadSubDirs[preloadSetIx]);
	
	preloadSubDir = preloadSubDirs[preloadSetIx];
	
	if ( preloadInit )
	{
		preloadIx = 0;
	}
	else
	{
		// carry on from where we left of in phase init
		preloadIx = preloadInitLimits[preloadSetIx];
		trace('### restarting set ' + preloadSetIx + ' at ' + preloadIx);
	}
	preloadImage();
}

/*----------------------------------------------------------------------------
preloadNextSet

When we've finished loading all images in a set or have reached the init limit
for that set in phase 0.

When we've done all the sets, if we're in the init phase, now is the time to
initialize the slideshow display, and autoStart if required. And a call to
preloadImages will cause image preloading to carry on from where it got up
to. If we've finished loading all sets after second phase, then we're done
and the progress bar can be hidden.

Otherwise, just move on to the next set.
----------------------------------------------------------------------------*/
function preloadNextSet()
{
	preloadSetIx++;
	if ( preloadSetIx >= preloadSubDirs.length )
	{
		if ( preloadInit )
		{
			trace('preload phase 0 COMPLETE - init display');
			
			// initialize display ( if required )
			if ( slideshow )
			{
				if ( autoStart )
				{
					trace('autoStart - setting index to: ' + autoStartIndex);
					imageIx = autoStartIndex;
				}
				showSlide();
				preloadNextSlide();
				showThumbs();
			}
			
			preloadInit = false;
			preloadImages();
			
			// can now autoStart	
			if ( autoStart )
			{
				onStartStop();
			}
			
		}
		else
		{
			trace('preload sets COMPLETE');
			
			sliderProgressBar.setOptions( {duration: 1000} );
			sliderProgressBar.slideOut('vertical');

			// set a timer to make sure this does happen
			// - think it gets stuck if it hasn't finished slide In
			//   when slide Out requested

			var fn = "tidyUpProgressBar()";
			timerSweeper = setTimeout(fn,2000);
		}
	}
	else
	{
		preloadSet();
	}
}

/*----------------------------------------------------------------------------
tidyUpProgressBar

Some times the progress bar gets stuck. I suspect at least cause is when the
request to slideOut happens before the slideIn has completed. So, we try
again here just to be sure.
----------------------------------------------------------------------------*/
function tidyUpProgressBar()
{
	trace('tidyUpProgressBar');
	sliderProgressBar.setOptions( {duration: 1000} );
	sliderProgressBar.slideOut('vertical');
	
	clearTimeout( timerSweeper );
}

/*----------------------------------------------------------------------------
preloadImage

If we've loaded all the images, then move on to the next set with a defered
call to preloadNextSet.

If we're in the first phase, then once we've reached the init limit for that
set, move onto to the next one.

Otherwise, initiate preload of the next image. The loaded() function is
called once the image has been downloaded into browser cache. 
----------------------------------------------------------------------------*/
function preloadImage()
{
	if ( preloadIx >= imageCount )
	{
		trace('preload COMPLETE');
		
		var fn = "preloadNextSet()";
		setTimeout(fn,10);
		return;
	}
	
	trace('preloadImage: ' + filenameArray[preloadIx] + ', ix: ' + preloadIx + ', count: ' + imageCount + ', size: ' + preloadSubDir);

	// reached limit for init phase?
	if ( preloadInit )
	{
		if ( preloadIx >= preloadInitLimits[preloadSetIx] )
		{
			trace('- phase 0 done');
		
			var fn = "preloadNextSet()";
			setTimeout(fn,10);
			return;
		}
	}
	
	// ok, can preload the next image
	imageFile = imageStore+preloadSubDir+'/'+filenameArray[preloadIx];
	image = new Image();
	image.onload = function()
	{
		loaded(); 
	}
	image.src = imageFile;
		
	imageArray.push( image );
}

/*----------------------------------------------------------------------------
loaded

To be able to update div with loading message AND then update it with image
when loaded, have to introduce this  timer in between ... presumably so that
the two updates are handled on separate threads, as in second update is
ignored because first hasn't been flushed yet
----------------------------------------------------------------------------*/
function loaded()
{
	trace('loaded: ix:' + preloadIx + ' for: ' + preloadSubDirs[preloadSetIx]);
	var fn = "preloadNext()";
	setTimeout(fn,10);
}

/*----------------------------------------------------------------------------
preloadNext

An image has successfully downloaded to browser cache. Update counts and
any progress bar in use. Then, move onto next image with a defered call to
preloadImage()
----------------------------------------------------------------------------*/
function preloadNext()
{	
//	trace('preloadNext: ' + preloadIx);
	
	// Update index of next image and count of how many loaded
	preloadCount++;
	preloadIx++;

	// Progress bar ...
	progressBarId = 'progressBar';
	var progressBar = getObjectById( progressBarId );
	
	progress = Math.round((preloadCount * 100) / (imageCount * preloadSubDirs.length));
	
//	trace('progress: ' + preloadCount + '(' + imageCount + ') ' + progress);
	if ( null != progressBar )
	{
		progressBar.style.width = progress+'%';
	}
	
	// after show, pause a little before activating next preload
	// so that images actually pop up in order 
	// this may not be necessary when actually deployed
	var fn = "preloadImage()";
	setTimeout(fn,10);
}


/*============================================================================
Slideshow control

Once started, the animation of the slideshow is handled by a state machine
that decides what to do every 50th of a second (tick). The slideshow is always
in a certain state (or phase) indicated by which phaseXXX var is true. And,
it is always counting up ticks (phaseTick) since start of that phase until it 
reaches the number of ticks for that phase e.g. fadeTicks which is calculated
from the timing information provided to the snippet e.g. 1000ms for showTime
results in showTicks being 50;
=============================================================================*/

/*----------------------------------------------------------------------------
handleNextStep

Handle the next tick in the slideshow timer events.

Slideshow controlled by three phases:
- phaseFadeOut: where current images slowly disappears. At end of this phase
  the next image is loaded in but can't be seen as its faded out
- phaseFadeIn: where new image slowly appears.
- phaseDirect: current image is faded out and next image underneath it is
  faded in.
- phaseShow: where new image is displayed without fading.

After processing the step, the next timer event is setup for the next step.
----------------------------------------------------------------------------*/
function handleNextStep()
{
	if ( phaseFadeOut )
	{
		if ( phaseTick < fadeTicks )
		{
			// keep fading
			phaseTick++;
			fade = (fadeTicks - phaseTick) / fadeTicks;
			fadeImage( fade );
		}
		else
		{
			// phase complete
//			trace('fadeOut complete - start fadeIn');
			phaseFadeOut = false;
			phaseFadeIn = true;
			
			// reset ticks
			phaseTick = 0;
			
			// 'display' next image but faded out
			nextSlide( true );
			fadeImage( 0 );
		}
	}
	else if ( phaseFadeIn )
	{
		if ( phaseTick < fadeTicks )
		{
			// keep fading
			phaseTick++;
			fade = phaseTick / fadeTicks;
			fadeImage( fade );
		}
		else
		{
			// phase complete
//			trace('fadeIn complete - start show');
			phaseFadeIn = false;		
			phaseShow = true;
			
			// reset ticks
			phaseTick = 0;
		}
	}
	else if ( phaseDirect )
	{
		if ( phaseTick < fadeTicks )
		{
			// keep fading
			phaseTick++;
			fade = (fadeTicks - phaseTick) / fadeTicks;
			fadeImage( fade );
		}
		else
		{
			// phase complete
//			trace('direct complete - start show');
//			trace((new Date).getTime());
			phaseDirect = false;		
			phaseShow = true;
			
			// reset ticks
			phaseTick = 0;
			
			// display next image - show in top layer without fade
			nextSlide( true );
			fadeImage( 1 );
		}
	}
	else if ( phaseShow )
	{
		if ( phaseTick < showTicks )
		{
			// keep showing
			phaseTick++;
		}
		else
		{
			trace('# is next image ready? imageIx,preloadIx,imageCount,preloadCount '+imageIx+','+preloadIx+','+imageCount+','+preloadCount);
			
			// if preloading AND next image but one is not preloaded, then just keep showing this image
			if ( preloadCount < imageCount && (preloadIx-1) <= imageIx )
			{
				trace('### re-show current image 3');
			}
			else
			{
				// phase complete
				phaseShow = false;
				
				// what's next depends on transition in use
				switch ( transition )
				{
					case 'fadeInOut':
//						trace('show complete - start fadeOut');
//						trace((new Date).getTime());
						phaseFadeOut = true;
						break;
					case 'fadeDirect':
//						trace('show complete - start direct');
//						trace((new Date).getTime());
						phaseDirect = true;
						break;
				}
			}
			
			// reset ticks
			phaseTick = 0;
		}
	}
	
	// next step ...
	showNextStep();
}

/*----------------------------------------------------------------------------
showNextStep

Create a timer to fire for next step in slideshow sequence.
----------------------------------------------------------------------------*/
function showNextStep()
{
	playTimer = setTimeout("handleNextStep()",20);
}


/*============================================================================
Gallery control

Process request by user or slideshow to display next or prev slide.
=============================================================================*/

/*----------------------------------------------------------------------------
prevSlide

Move to previous slide
----------------------------------------------------------------------------*/
function prevSlide()
{
	if ( imageIx > 0 )
	{
		imageIx--;
		showSlide();
	}
}

/*----------------------------------------------------------------------------
nextSlide

Move to next slide, with option to support wrapping round to start of list
used for slideshow. Also, make sure next image is loaded ready.
----------------------------------------------------------------------------*/
function nextSlide( wrap )
{
	if ( imageIx < imageCount-1 )
	{
		imageIx++;
		showSlide();
		preloadNextSlide();
	}
	else if ( wrap )
	{
		imageIx = 0;
		showSlide();
		preloadNextSlide();
	}
}

/*----------------------------------------------------------------------------
preloadNextSlide

Load the next image into a hidden div so that its ready for when slideshow
gets to it or user presses next.

Image preloading probably means this isn't necessary but it won't hurt.
----------------------------------------------------------------------------*/
function preloadNextSlide()
{
	var nextImageIx = imageIx + 1;
//	trace('preloadNextSlide: '+nextImageIx);
	
	if ( nextImageIx == imageCount )
	{
		nextImageIx = 0;
	}
	
	var nextImageFile = imageStore+slideSubDir+'/'+filenameArray[nextImageIx];
	var nextViewerId = viewerId+'Next';
	var nextSlide = getObjectById(nextViewerId);
	if ( nextSlide != null )
	{
		nextSlide.src = nextImageFile;
	}
}


/*============================================================================
Display functions

Various functions that directly update what is displayed in the browser.
=============================================================================*/

/*----------------------------------------------------------------------------
updateTagList

When the user selects a tag from the tag selector or the photo gallery is
requested with a tag specified as a GET parameter, then the tag list needs
to show that tag highlighted.

Once we've found the 'tagList' object, it is an easy job to go through the
TABLE and update the tag in question, resetting all others.

Since the tag list can be displayed asynchronously from the gallery view, it
might not be ready when the gallery is first displayed. So, try a few times
before giving up completely.
----------------------------------------------------------------------------*/
function updateTagList(tag)
{
	trace('updateTagList: ('+tag+')');
	
	clearTimeout(tagListTimer);
	
	// update tag highlighting
	tagListTable = getObjectById('tagList');
	if ( null != tagListTable )
	{
		// process TRs, highlight just the one(s) in tag
		ix = 0;
		tagId = 'tag_'+tag;
		while ( ix < tagListTable.rows.length )
		{
			tagListRow = tagListTable.rows[ix];
			if ( tagListRow.id == tagId )
			{
				tagListRow.style.background = '#fef4be';
			}
			else
			{
				tagListRow.style.background = '';
			}
			ix++;
		}
	}
	else
	{
		trace('- tagList NOT found with tag = ('+tag+')');
		if ( tagListTimerCount < 10 )
		{
			var fn = 'updateTagList(\''+tag+'\')';
			tagListTimerCount++;
			tagListTimer = setTimeout(fn,200);
		}
		else
		{
			trace('- give up!');
		}
	}
}

/*----------------------------------------------------------------------------
showGalleryControls

Display the mini slideshow control panel
----------------------------------------------------------------------------*/
function showGalleryControls()
{
//	trace('showGalleryControls');
	
	showControl('galleryControls'+'0');
	showControl('galleryControls'+'1');
}

/*----------------------------------------------------------------------------
hideGalleryControls

Hide the mini slideshow control panel
----------------------------------------------------------------------------*/
function hideGalleryControls()
{
//	trace('hideGalleryControls');
	
	hideControl('galleryControls'+'0');
	hideControl('galleryControls'+'1');
}

/*----------------------------------------------------------------------------
showFilmstripControls

Display the mini slideshow control panel
----------------------------------------------------------------------------*/
function showFilmstripControls()
{
//	trace('showFilmstripControls');
	
	showControl('filmstripControls'+'0');
	showControl('filmstripControls'+'1');
}

/*----------------------------------------------------------------------------
hideGalleryControls

Hide the mini slideshow control panel
----------------------------------------------------------------------------*/
function hideFilmstripControls()
{
//	trace('hideFilmstripControls');
	
	hideControl('filmstripControls'+'0');
	hideControl('filmstripControls'+'1');
}

/*----------------------------------------------------------------------------
showMiniControls

Display the mini slideshow control panel
----------------------------------------------------------------------------*/
function showMiniControls()
{
//	trace('showMiniControls');
	
	showControl('miniControls');
//	sliderMiniControls.slideIn('vertical');
}

/*----------------------------------------------------------------------------
hideMiniControls

Hide the mini slideshow control panel
----------------------------------------------------------------------------*/
function hideMiniControls()
{
//	trace('hideMiniControls');
	
	hideControl('miniControls');
//	sliderMiniControls.slideOut('vertical');
}

/*----------------------------------------------------------------------------
showControl

Display a control
----------------------------------------------------------------------------*/
function showControl(id)
{
//	trace('showControl: ' + id);
	var control = getObjectById(id);
	if ( null != control )
	{
		control.style.opacity = '1.0';
		control.style.filter = 'alpha(opacity=100)';
	}			
}

/*----------------------------------------------------------------------------
hideControl

Hide a control
----------------------------------------------------------------------------*/
function hideControl(id)
{
//	trace('hideControl: ' + id);
	var control = getObjectById(id);
	if ( null != control )
	{
		control.style.opacity = '0.0';
		control.style.filter = 'alpha(opacity=0)';
	}			
}

/*----------------------------------------------------------------------------
updateControls

Prev & Next buttons fade out when at start/end. They are also disabled
when doing slideshow.
----------------------------------------------------------------------------*/
function updateControls()
{
//	trace('updateControls');
	var btnPrev = getObjectById('btnPrev');
	if ( null != btnPrev )
	{
		if ( imageIx > 0 && !play )
		{
			btnPrev.style.opacity = '1.0';
			btnPrev.style.filter = 'alpha(opacity=100)';
		}
		else
		{
			btnPrev.style.opacity = '0.3';
			btnPrev.style.filter = 'alpha(opacity=30)';
		}
	}

	var btnNext = getObjectById('btnNext');
	if ( null != btnNext )
	{
		if ( imageIx < imageCount-1 && !play  )
		{
			btnNext.style.opacity = '1.0';
			btnNext.style.filter = 'alpha(opacity=100)';
		}
		else
		{
			btnNext.style.opacity = '0.3';
			btnNext.style.filter = 'alpha(opacity=30)';
		}
	}
	
	var btnPrevGroup = getObjectById('btnPrevGroup');
	if ( null != btnPrevGroup )
	{
		if ( stripIx > 0 && !play  )
		{
			btnPrevGroup.style.opacity = '1.0';
			btnPrevGroup.style.filter = 'alpha(opacity=100)';
		}
		else
		{
			btnPrevGroup.style.opacity = '0.3';
			btnPrevGroup.style.filter = 'alpha(opacity=30)';
		}
	}

	var btnNextGroup = getObjectById('btnNextGroup');
	if ( null != btnNextGroup )
	{
		if ( (stripIx+8) < imageCount && !play )
		{
			btnNextGroup.style.opacity = '1.0';
			btnNextGroup.style.filter = 'alpha(opacity=100)';
		}
		else
		{
			btnNextGroup.style.opacity = '0.3';
			btnNextGroup.style.filter = 'alpha(opacity=30)';
		}
	}
	
}

/*----------------------------------------------------------------------------
updateButtons

Update display of slideshow buttons & captions div
----------------------------------------------------------------------------*/
function updateButtons()
{
	trace('updateButtons');
	
	// slideshow button
	var btnSlideshow = getObjectById('btnSlideshow');
	if ( null != btnSlideshow )
	{
		trace('- found btnSlideshow');
		if ( play )
		{
			btnSlideshow.value = 'Stop';
		}
		else
		{
			btnSlideshow.value = 'Slideshow';
		}
	}
	
	// mini slideshow start/stop
	var btnShow = getObjectById('btnShow');
	if ( null != btnShow )
	{
		trace('- found btnShow');
		if ( play )
		{
			btnShow.src = 'assets/snippets/theGallery/icons/stop.png';
		}
		else
		{
			btnShow.src = 'assets/snippets/theGallery/icons/play.png';
		}
	}
	
	// captions button
	var btnCaptions = getObjectById('btnCaptions');
	if ( null != btnCaptions )
	{
		if ( showCaptions )
		{
			btnCaptions.value = 'Captions';
		}
		else
		{
			btnCaptions.value = 'Captions';
		}
	}
	
	// captions overlay
	var captionsDiv = getObjectById('caption');
	if ( null != captionsDiv )
	{
		if ( showCaptions )
		{
			captionsDiv.style.opacity = '0.8';
			captionsDiv.style.filter = 'alpha(opacity=80)';
		}
		else
		{
			captionsDiv.style.opacity = '0.0';
			captionsDiv.style.filter = 'alpha(opacity=0)';
		}
	}
	
}

/*----------------------------------------------------------------------------
showSlide

Update the image displayed. The id of the IMG object was provided to the
init() call. This function simply updates its src attribute with the URL of
the image. It also updates the title attribute for the hover tooltip, and
the text in the caption box.
----------------------------------------------------------------------------*/
function showSlide()
{
	trace('showSlide: imageIx='+imageIx);
	var imageFile = imageStore+slideSubDir+'/'+filenameArray[imageIx];
	var imageTitle = titleArray[imageIx];

	var viewer = getObjectById(viewerId);
	
	if ( null != viewer )
	{
		viewer.src = imageFile;
		viewer.title = imageTitle;
	}
	
	var caption = getObjectById('caption');
	if ( caption != null )
	{
		caption.innerHTML = imageTitle;
	}
}

/*----------------------------------------------------------------------------
showThumbs

Display the required group of thumbs in filmstrip
----------------------------------------------------------------------------*/
function showThumbs()
{
	thumbIx = 0;
	while ( thumbIx < 8 )
	{
		thisIx = thumbIx + stripIx;
		var thumbDivId = 'thumb'+thumbIx;
		var thumbDiv = getObjectById( thumbDivId );
		if ( null != thumbDiv )
		{
			if ( thisIx < imageCount )
			{
				imageFile = imageStore+thumbSubDir+'/'+filenameArray[thisIx];
				thumbDiv.src = imageFile;
			}
			else
			{
				thumbDiv.src = 'assets/snippets/theGallery/icons/missing.png';
			}
		}
		
		thumbIx++;
	}
}

/*----------------------------------------------------------------------------
fadeImage

Fade the displayed image to the specified value (between 0 and 1).

Fade the next image, if present, to the opposite fade.
----------------------------------------------------------------------------*/
function fadeImage( fade )
{
	var viewer = getObjectById(viewerId);
	
	if ( viewer != null )
	{
		viewer.style.opacity = fade;
		
		// For IE8, opacity doesn't work (typical Microsoft!) so have to do this aswell.
		// AND, some pure black dots appear white so when fade finished we turn off the
		// filter completely (Microsoft!!)
		percent = fade * 100;
		if ( fade == 1 )
		{
			viewer.style.filter = '';		
		}
		else
		{
			viewer.style.filter = 'alpha(opacity='+percent+')';
		}
	}
	
	var viewerNext = getObjectById(viewerId+'Next');
	
	if ( viewerNext != null )
	{
		fadeNext = 1 - fade;
		
		viewerNext.style.opacity = fadeNext;
		
		// For IE8, opacity doesn't work (typical Microsoft!) so have to do this aswell.
		percent = fadeNext * 100;
		viewerNext.style.filter = 'alpha(opacity='+percent+')';
	}
	
}


/*============================================================================
AJAX support
=============================================================================*/

/*----------------------------------------------------------------------------
ajaxGallery

Construct and post an AJAX request to the Gallery snippet
----------------------------------------------------------------------------*/
function ajaxGallery(
	viewerId,
	debug, 
	view, 
	tag, 
	width, 
	height, 
	linkUrl,
	linkTag,
	randomImage,
	slides,
	transition,
	showTime,
	fadeTime,
	autoStart,
	autoStartIndex
	)
{
	trace('ajaxGallery - ('+autoStart+')');
	
	var url = _base + 'theGalleryAjaxServer.php';
	var pars = Object.toQueryString({
		q:				url,
		debug:			debug,
		call:			'AJAX',
		view:			view,
		tag:			tag,
		width:			width,
		height:			height,
		linkUrl:		linkUrl,
		linkTag:		linkTag,
		randomImage:	randomImage,
		slides:			slides,
		transition:		transition,
		showTime:		showTime,
		fadeTime:		fadeTime,
		autoStart:		autoStart,
		autoStartIndex:	autoStartIndex
	});
	
	new Ajax('index-ajax.php', {postBody: pars, update: $(viewerId), evalScripts: true }).request();
}




/*============================================================================
OBSOLETE CODE - DELETE
=============================================================================*/

/*----------------------------------------------------------------------------
showControls

----------------------------------------------------------------------------*/
function XXX_showControls(id)
{
	trace('showControls: ' + id);

	showControl(id);
	showControl(id+'0');
	showControl(id+'1');
}

/*----------------------------------------------------------------------------
hideControls

----------------------------------------------------------------------------*/
function XXX_hideControls(id)
{
	trace('hideControls: ' + id);
	
	hideControl(id);
	hideControl(id+'0');
	hideControl(id+'1');
}


/*
//
// Ajax call to display slideshow
//
function getGalleryView(debug, tags, width, height, slides, showTime, fadeTime)
{
	alert('getGalleryView');
	trace('getGalleryView - '+tags+','+width+','+height+','+slides+','+showTime+','+fadeTime);
	var url = _base + 'theGalleryAjaxServer.php';
	var pars = Object.toQueryString({
		q:			url,
		debug:		debug,
		view:		'gallery',
		tags:		tags,
		width:		width,
		height:		height,
		slides:		slides,
		showTime:	showTime,
		fadeTime:	fadeTime
	});
	
	new Ajax('index-ajax.php', {postBody: pars, update: $('viewerGallery'), evalScripts: true }).request();
}

// getMiniView(1, 'null', null, null, yes, 1000, 200, 'http://localhost/other/gallery.html?tags=5');
function getMiniView(debug, tags, width, height, slides, showTime, fadeTime, autoStart, linkUrl)
{
	alert('getMiniView');
	trace('getMiniView - '+fadeTime+','+linkUrl);
	var url = _base + 'theGalleryAjaxServer.php';
	var pars = Object.toQueryString({
		q:			url,
		view:		'mini',
		tags:		tags,
		width:		width,
		height:		height,
		slides:		slides,
		showTime:	showTime,
		fadeTime:	fadeTime,
		autoStart:	autoStart,
		linkUrl:	linkUrl
	});
	
	new Ajax('index-ajax.php', {postBody: pars, update: $('viewerMini'), evalScripts: true }).request();
}

function getBannerView(tags, width, height, slides, showTime, fadeTime)
{
	alert('getBannerView: '+slides);
	var url = _base + 'theGalleryAjaxServer.php';
	var pars = Object.toQueryString({
		q:			url,
		view:		'banner',
		tags:		tags,
		width:		width,
		height:		height,
		slides:		slides,
		showTime:	showTime,
		fadeTime:	fadeTime
	});
	
	new Ajax('index-ajax.php', {postBody: pars, update: $('viewerBanner'), evalScripts: true }).request();
}

function getTagsSideBar(tags)
{
	alert('getTagsSideBar');
	var url = _base + 'theGalleryAjaxServer.php';
	var pars = Object.toQueryString({
		q:		url,
		view:	'tags',
		tags:	tags
	});
	
	new Ajax('index-ajax.php', {postBody: pars, update: $('viewerTags'), evalScripts: true }).request();
}
*/

// ===========================================================================
// onChangeFilter
//
// User changed the filter ... to show all/select a tag
// ===========================================================================
function onChangeFilterXXX()
{
	try
	{
		alert('onChangeFilter');
		
		// assume all tags
		tags = ''
		
		// check if tag selected
		tagsSelect = getObjectById('tags');
//		alert('tagsSelect: '+tagsSelect);
		if ( null != tagsSelect )
		{
//			alert('tagsSelect.value: '+tagsSelect.value);
			tags = tagsSelect.value;
		}
		
//		alert('tags: '+tags);
		viewCtrl = getObjectById('view');
		if ( null != viewCtrl )
		{
			view = viewCtrl.value;
		}
//		alert('view:'+view);
		switch (view)
		{
			/*
			case 'table':
				getTableView(tags);
				break;
			*/
			case 'slides':
			default:				
				// automatically stop slideshow if running
				var autoStart = false;
				if ( play )
				{
					onStartStop();
				}
				
				// do Ajax call
				getGalleryView(true, tags);
				break;
		}
	}		
	catch (ex)
	{
		reportException(ex);
	}
}
// ===========================================================================
// handleRestart
//
// When change filter with slideshow running, the slideshow is restarted
// after Ajax call to get new selection. Needs to be handled as an event,
// not 'inline' with the Ajax call.
// ===========================================================================
function handleRestartXXX()
{
	clearTimeout( restartTimer );
	
	onStartStop();
}
// should updateTagList be called from here OR initGallery()???
// - initGallery() is essentially called when the response is complete
/*
function onAjaxResponse(tags)
{
	try
	{
		trace('onAjaxResponse: ' + tags);
		
		updateTagList(tags);
	}
	catch (ex)
	{
		reportException(ex);
	}
}

function onAjaxResponseMini()
{
	try
	{
		trace('onAjaxResponseMini ' + initialized);
		
		// auto start
//		onStartStop();
	}
	catch (ex)
	{
		reportException(ex);
	}
}

function onAjaxResponseBanner()
{
	try
	{
		trace('onAjaxResponseBanner ' + initialized);
		
		// auto start
//		onStartStop();
	}
	catch (ex)
	{
		reportException(ex);
	}
}
*/
/*----------------------------------------------------------------------------
startSlideShow
----------------------------------------------------------------------------*/
function startSlideShowXXX()
{
	alert('startSlideShow');
	
	onStartStop();
}



