// ---- LICENSING INFORMATION ----
// Copyright:	The Natural History Museum, London, England, 2005 
// Author: 		Mike Sadka
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details (http://www.gnu.org/copyleft/gpl.html).
// For a copy of the GNU General Public License write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
// ---- END LICENSING INFO ----


// -- script to implement slideshows --
// author: 			Mike Sadka
// created: 		Feb-April 2005 (version 1)
// updated: 		March 2009 (fixed conflict with tab script caused by URL# processing to change initial slide)
//					NOT IDEAL - possible to leave tab with slideshow, only to return to a show which isn't running but says "stop" in the controls...
//					PLUS needs proper x-browser testing...
// 					SOLUTION: best solution prob to change both scripts to HIDE tabs/slides rather than REMOVE them - that way the scripts should continue to run even if not on the current tab...

/***** INITIALISE *****/

var ssCurrSlideIndex = 0;											// initialise
var ssMaxSlideIndex = -1;											// initialise
var ssSlides = new Array();											// temporary array of slide object references
var ssRestartable = false;											// initialise
if (typeof ssInterval == 'undefined') var ssInterval = 10000;		// set default milliseconds to display each slide if not already set
if (typeof ssTileWidth == 'undefined') var ssTileWidth = 62;		// set default tile width if not already set - prob unnec as CSS should do this
if (typeof ssLoop == 'undefined') var ssLoop = false;				// set default loop status
if (typeof ssRunning == 'undefined') var ssRunning = false;			// set default run status (NO auto-run)
if (typeof ssSelectable == 'undefined') var ssSelectable = true;	// set default creation of tile selector

// print flag - prevents execution of slideshow when being printed via "print this page" jsp app.
// can prob remove this from here as now in nhm.js - miks - 03/2009
var formatForPrint = (document.location.href.indexOf('print-version') != -1);

if ((W3CDOM) && (!formatForPrint)) {
	window.addOnload(ssSetUp);
}


/***** SETUP *****/
function ssSetUp() {
	if (!W3CDOM) return;													// exit if not dom-compliant browser
	ssSlideshowContainer = document.getElementById('ssSlideshow');			// get entire slideshow div as global object ref

	if (ssSlideshowContainer == null) return;								// exit if no slideshow XHTML present
	
	ssSlideshowContainer.style.visibility = 'hidden';						// hide initially so processing not visible to user
	ssSlides = getElementsByClassName('ssSlide');							// transfer all slide markup to ssSlides array
	ssMaxSlideIndex = ssSlides.length - 1;									// set max slide index value (ie - one less than number of slides)
	for (var i=0;i<ssSlides.length;i++) { 									// for each slide div...
		ssSlides[i].id = 'ssSlide' + i;										// add slide IDs (so can be identified by ssCreateSelector function)
	}
	for (i=0;i<ssSlideshowContainer.childNodes.length;i++) {				// delete all slides (and other text nodes) from slideshow div in HTML source 
		ssSlideshowContainer.removeChild(ssSlideshowContainer.lastChild)
		i--;																// otherwise not all nodes get removed - because the array is being shortened, if i is incremented, nodes get skipped
	}
	ssSlideshowContainer.appendChild(ssCreateControls());				// append control-links div as first child of ssSlideshow
	var ssFirstSlide = ssSlides[ssInitialSlide()];						// re-instate initial (first, unless otherwise specified) slide 
	ssSlideshowContainer.appendChild(ssFirstSlide);
	if (ssSelectable) ssCreateSelector();								// create tile selector - AFTER first slide appended so ssCurrSlideIndex correct
	if (ssSelectable) ssSlideshowContainer.appendChild(ssSelector);		// need to at append selector AFTER slides removed, or it also gets removed
	ssSlideshowContainer.style.visibility = 'visible';					// re-show
	if (ssRunning) ssRun();												// auto-run if ssRunning == true (default is false)
}
function ssCreateControls() {
	ssControllor = document.createElement('DIV');			// create container
	ssControllor.id = 'ssControls';
	ssControllor.className = 'ssMenubar';

	ulTag = document.createElement('UL');					// create menu
	
	liNext = document.createElement('LI');					// create item
	aTag = document.createElement('A');						// create next link
	aTag.id = 'ssNextLink';
	aTag.name = 'nextlink';	
	aTag.href = '#';
	aTag.className = 'pointRight point-right';				// both versions for backward compatibility - remove original when fully standardised
	aTag.title = 'Next slide';
	aTag.onclick = ssNext;
	t = document.createTextNode('Next slide');
	aTag.appendChild(t);
	liNext.appendChild(aTag);
	ulTag.appendChild(liNext);

	liRunStop = document.createElement('LI');				// create item
	aTag = document.createElement('A');						// create run/stop link
	aTag.id = 'ssRunStopLink';
	aTag.name = 'runstoplink';	
	aTag.href = '#';
	aTag.className = 'pointRight point-right';			  // both versions for backward compatibility - remove original when fully standardised
	aTag.title = 'Run slideshow';
	aTag.onclick = ssRun;
	t = document.createTextNode('Run');
	aTag.appendChild(t);
	liRunStop.appendChild(aTag);
	ulTag.appendChild(liRunStop);	

	liPrev = document.createElement('LI');					// create item
	aTag = document.createElement('A');						// create previous link
	aTag.id = 'ssPrevLink';	
	aTag.name = 'prevlink';	
	aTag.href = '#'; 										// not initially...???
	aTag.className = 'pointLeft point-left disabled';			// both versions for backward compatibility - remove original when fully standardised
	aTag.title = 'Previous slide';
	aTag.onclick = ssVoid;									// set function as method, so can access index value via this.id
	t = document.createTextNode('Previous slide');
	aTag.appendChild(t);
	liPrev.appendChild(aTag);
	ulTag.appendChild(liPrev);

	ssControllor.appendChild(ulTag);
	return ssControllor;
}

function ssCreateSelector() {
	ssSelector = document.createElement('DIV');				// create tile selector div
	ssSelector.id = 'ssTileSelector';
	for (i=0;i<ssMaxSlideIndex+1;i++) {						// create tiles
		var bool = (i == ssCurrSlideIndex);
		ssSelector.appendChild(ssCreateTile(i, bool));
	}
	//alert(ssSelector.outerHTML);
}

function ssCreateTile(index, status) {
// status: true (current tile) or false (clickable tile)

	slide = ssSlides[index];								// get ref to image of currrent slide
	slideImageObj = slide.getElementsByTagName('IMG');
	slideImageFile = slideImageObj[0].src;

	// ORIGINALLY, script assumes thumbnails will be 1 level lower than images in /tns - we will need to change this assumption for Rx-published image files
	// NOW rx-specific - adds '_th' to filename before '_[ContentID]' at end of filename
	// POSS needs an alternative for use with non-rx-generated images...
	lastUnderscorePos = slideImageFile.lastIndexOf('_');	// create thumbnail path and filename
	firstSrcPart = slideImageFile.substring('0',lastUnderscorePos);
	lastSrcPart = slideImageFile.substring(lastUnderscorePos);
	thumbImageFile = firstSrcPart + '_th' + lastSrcPart;

	imageTag = document.createElement('IMG');		// create image tag
	imageTag.src = thumbImageFile;
	imageTag.removeAttribute('width');				// actual width of image gets inserted automatically, so remove it (although would be fine if using correct thumbnail sizes...)
	imageTag.removeAttribute('height');				// actual height of image gets inserted automatically, so remove it
	imageTag.width = ssTileWidth;					// best to set this anyway? - but CSS rule should control tile width
	imageTag.height = ssTileWidth;					// best to set this anyway? - but CSS rule should control tile width
	imageTag.border = '2';							// if don't do this, Opera (and Safari?) has no image borders
	
	aTag = document.createElement('A');				// create A-tag
	if (status) {									// create current tile
		aTag.className = 'ssCurrTileLink';
		aTag.onclick = ssVoid;						// set function as method, so can access index value via this.id
	 	imageTag.className = 'ssCurrTileImage';
	} else {										// create clickable tile
		aTag.className = 'ssTileLink';
		aTag.onclick = ssSelectSlide;				// set function as method, so can access index value via this.id
		//aTag.onmouseover = ssFakeHover_on;
		//aTag.onmouseout = ssFakeHover_off;
		imageTag.className = 'ssTileImage';
	}
	aTag.appendChild(imageTag);
	aTag.id = index;								// this may conflict with any other scrip that uses numeric IDs
	aTag.href = '#';

	return aTag;
}
function ssInitialSlide() {
var ssInitialSlideIndex = 0;						// initialise
// NOTE - index starts at 0 but hash uses position, starting at 1
// this doesn't work if already on slideshow page, but works loading from a link
// could use an http param and parse it from the URL if preferable
// NOTE: does not enable "previous slide link" appropriately when this happens

	//alert(document.location.hash.indexOf('slide') == 1)

	//ORIG: if (location.hash.length > 1) { ssInitialSlideIndex = location.hash.substring(1) - 1; }
	
	// if url# == 'slide*'
	if (location.hash.indexOf('slide') == 1) { ssInitialSlideIndex = location.hash.substring(6) - 1; }
	
	//alert(ssInitialSlideIndex);
	
	ssCurrSlideIndex = ssInitialSlideIndex;	
	return ssInitialSlideIndex;
}


/***** FIX *****/
// this really shouldn't be required, but helps avoid dodgy IE bug (do not have to remove href from link, which causes IE issues)
function ssVoid() {
	this.blur();
	return false;
}

/***** OPERATE *****/
function ssRun() {
	if (ssRestartable) {				// restartable is true only after show has ended without looping, and before any other action has occurred
		ssShowSlide(0);
		setTimeout(ssRun,ssInterval);
		ssRestartable = false;
		ssSetNext(false);
	} else {
		if (!ssRunning) { 
			ssNext();
			ssRunning = true; 
		}
		ssRunStop(true);
		process = setInterval('ssNext();',ssInterval);
		ssSetNextPrev();
	}
	return false;						// so links not followed
}

function ssStop() {
	ssRunning = false;
	if(typeof process != 'undefined') clearInterval(process);
	ssRunStop(false);
	ssSetNextPrev();
	return false;						// so links not followed
}

//function ssStopDead() {
//// used to completely stop execution to prevent errs when slideshow on a tab and tab switched...
//	ssRunning = false;
//	if(typeof process != 'undefined') clearInterval(process);
//}

function ssRunStop() {
// innerHTML is not a DOM standard, but is useful and very widely supported - miks
	ssRSLink = document.getElementById('ssRunStopLink');
	ssRSLink.innerHTML = (ssRunning? 'Stop' : 'Run');
	ssRSLink.title = (ssRunning? 'Stop slideshow' : 'Run slideshow');
	if (ssRunning) {
		ssRSLink.onclick = ssStop;
	} else {
		ssRSLink.onclick = ssRun;
	}
}

function ssSetNextPrev() {
	if (ssRunning) {
		ssSetNext(false);
		ssSetPrev(false);
	} else {
		if (ssCurrSlideIndex > 0) ssSetPrev(true);
		if (ssCurrSlideIndex == 0) ssSetPrev(false);
		if (ssCurrSlideIndex < ssMaxSlideIndex) ssSetNext(true);
		if (ssCurrSlideIndex == ssMaxSlideIndex) ssSetNext(ssLoop);
	}
}

function ssSetNext(status) {
	ssNLink = document.getElementById('ssNextLink');
	if(status) {
		ssNLink.onclick = ssNext;
		//ssNLink.href = '#';
		ssNLink.className = 'pointRight point-right';
	} else {
		ssNLink.onclick = ssVoid;
		//ssNLink.removeAttribute('onclick');
		//ssNLink.removeAttribute('href');
		ssNLink.className = 'pointRight point-right disabled';
	}
}

function ssSetPrev(status) {
	ssPLink = document.getElementById('ssPrevLink');
	if(status) {
		ssPLink.onclick = ssPrev;
		//ssPLink.href = '#';
		ssPLink.className = 'pointLeft point-left';
	} else {
		ssPLink.onclick = ssVoid;
		//ssPLink.removeAttribute('onclick');
		//ssPLink.removeAttribute('href');
		ssPLink.className = 'pointLeft point-left disabled';
	}
}

function ssPrev() {
	if (ssCurrSlideIndex > 0) {
		var newSlideIndex = ssCurrSlideIndex - 1;
		ssShowSlide(newSlideIndex);
		ssCurrentSlide(newSlideIndex);
	}
	return false;															// so links not followed
}

function ssNext() {
//alert("ssNext");
	var newSlideIndex = (ssCurrSlideIndex - 0) + 1;							// -0 forces number datatype, but why this is necessary I have no idea (otherise SOMETIMES gets concatenated rather than summed
	if (newSlideIndex == ssMaxSlideIndex) {									// about to move to last slide
		if (!ssLoop) {
			if (ssRunning) ssRestartable = true;							// end of slideshow - if not looping, run should restart
			ssStop();
		}
	}
	if (newSlideIndex > ssMaxSlideIndex) newSlideIndex = 0;					// loop
	ssShowSlide(newSlideIndex);	
	return false;															// don't follow # href
}

function ssSelectSlide() {
	if(typeof process != 'undefined') ssStop();								// stop slideshow if already running	
	ssShowSlide(this.id);													// only called as method of tiles 
	return false;															// don't follow # href
}

function ssShowSlide(index) {												// replace current slide with new slide
//alert("ssShowSlide");
	ssRestartable = (index == ssMaxSlideIndex ? true : false);				// set to true when slideshow ends without looping, but should only be true at that point, so reset if move previous - BUT maybe not needed if ssShowSlide does it...

	if (index != ssCurrSlideIndex) {
		var newSlide = ssSlides[index];
		var oldSlide = document.getElementById('ssSlide' + ssCurrSlideIndex);
		
		// ADDED TO FIX PROBS WITH SLIDESHOWS ON TABS - NOT REALLY EFFECTIVE...
		// if oldSlide is NULL then probably should stop (eg - the slideshow was running on a tab which is no longer the active tab)
		//if (oldSlide == null) {
		//	ssStopDead();
		//	return;
		//}
		
		ssSlideshowContainer.replaceChild(newSlide,oldSlide);
		ssCurrTile(index);
		ssCurrentSlide(index);												// do this last, so original index available to ssCurrTile function
	}
	// if control enablement may have changed, check and set it appropriately
	if ((index == 0) || (index == 1) || (index == ssMaxSlideIndex) || (index == ssMaxSlideIndex - 1)) ssSetNextPrev();
}

function ssCurrentSlide(index) {
	ssCurrSlideIndex = index;
}

function ssCurrTile(index) {
// hover styles do not work in Safari or Opera - could fix this by using js to swap classes rather then relying on hover events... - miks
	if (!ssSelectable) return;					 							// exit if no tiles
	var oldTileLink = document.getElementById(ssCurrSlideIndex);
		oldTileLink.onclick = ssSelectSlide;
		oldTileLink.className = 'ssTileLink';
		oldTileLink.firstChild.className = 'ssTileImage';
		//aTag.onmouseover = ssFakeHover_on;
		//aTag.onmouseout = ssFakeHover_off;
	var newTileLink = document.getElementById(index);
		newTileLink.onclick = ssVoid;
		newTileLink.className = 'ssCurrTileLink';
		newTileLink.firstChild.className = 'ssCurrTileImage';
		newTileLink.blur();
		//aTag.onmouseover = ssVoid;
		//aTag.onmouseout = ssVoid;
}

// these functions explicitly change classes to achieve hover effect without CSS - prob completely unnec as Opera and Safari still don't show it - miks
function ssFakeHover_on() {
	this.className = 'ssTileLink_fakeHover';
}
function ssFakeHover_off() {
	this.className = 'ssTileLink';
}