
// SS/TN Settings are modified on a per-site basis
Settings = new Array();


// This is the absolute path to where the images are located, must end with "/"
Settings.folder = "http://www.tropicalvillavacations.com/images/ov-SunSplashSuiteWaileaBeachVillas/";

Settings.preventImageTheft = false; // Set to either true or false; true prevents right-clicking

// 4) Controls ProgressBar colors & width
Settings.TN = new Array();
Settings.TN.ProgressBar = new Array();

// ProgressBar: Set to true or false. Always seet true unless you are wanting to choose new colors.
// By setting it to false it will not dissapear, which allows you to style it with new colors per settings below
Settings.TN.ProgressBar.hideOnSuccess = true;

Settings.TN.ProgressBar.width = 300;

// If you prefer hex colors you may use them starging with # like so: "#ffffff"
Settings.TN.ProgressBar.progressColor = "rgb( 0,0,0 )";
Settings.TN.ProgressBar.bgColor = "E58D45";
Settings.TN.ProgressBar.fontColor = "rgb( 255,255,255 )";
Settings.TN.borderColorOff = "rgb( 62,0,0 )";
Settings.TN.borderColorOn = "rgb( 255,204,153 )";

// Title: Will appear above thumbnails and below progress bar
Settings.TN.pageTitle = "Click Photos to Enlarge";

//----------------------------------- Begin Global Functions ---------------------------------

// Getters
function gId( str ) { return document.getElementById( str ); }
function gTn( str ) { return document.getElementsByTagName( str ); }
function gEl( str ) { return document.createElement( str ); }

// Setters
function aCh( Obj ) { document.body.appendChild( Obj ); }
function rCh( Obj ) { document.body.removeChild( Obj ); }

//----------------------------------- End Global Functions ---------------------------------

///////////////////////////////// BEGIN PROTOTYPES /////////////////////////////////


//----------------------------------- String Prototype -----------------------------------
// If key is found in strToSearch then returns its value, otherwise returns null
function getVal( key ) {

	var value = null;
	var strToSearch = this.toString();

	var KeyVals = strToSearch.split( "&" );

	for( member in KeyVals ) {
		var ThisPair = KeyVals[ member ].split( "=" );
		if( key == ThisPair[ 0 ] ) { value = ThisPair[ 1 ]; break; }
	}
	if( typeof value == "undefined" ) value = "";
	return value;
}
String.prototype.getVal = getVal;


//----------------------------------- String Prototype -----------------------------------
// Trims white space (which includes line breaks) off both ends
function trim() {
	var str = this.toString();
	return str.replace( /^\s*|\s*$/g, "" );
}
String.prototype.trim = trim;

///////////////////////////////// END PROTOTYPES /////////////////////////////////


var IE = false, oldIE = false, AOL = false, SF = false, MZ = false, OP = false;
var navAppName = navigator.appName, navUserAgent = navigator.userAgent;

switch( navAppName.toLowerCase() ) {

	case "microsoft internet explorer":
		IE = true;
		if( /AOL/.test( navUserAgent ) ) AOL = true;
		if( parseFloat( navUserAgent.split( "MSIE" )[ 1 ] ) <= 6 ) oldIE = true;
		break;

	case "netscape":
		if( /Chrome/i.test( navUserAgent ) ) MZ = true;
		else if( /Safari/i.test( navUserAgent ) ) SF = true;
		else MZ = true;
		break;

	case "opera":
		OP = true;
		break;

}

var winOS = ( navigator.platform.substring( 0, 3 ) == "Win" );
var macOS = ( navigator.platform.substring( 0, 3 ) == "Mac" );

var theHost = document.location.hostname;

var local = ( /^\d+\.\d+\.\d+\.\d+$/.test( theHost ) || theHost == "" || theHost == "localhost" );
// if( theHost = "74.208.97.125" ) local = false; // Activate if remote site is available via an IP address
var live = !local;

var emailRE = /^[\w\.-]*[^\.-]@[\w\.-]+\.[a-zA-Z]{2,}$/;

var qStr = unescape( document.location.search ).substring( 1 );

var homePage = "index.aspx"
var path = document.location.pathname;
var delimeter = ( path.indexOf( "\\" ) >= 0 ) ? "\\" : "/";
if( path.charAt( path.length - 1 ) == delimeter ) path += homePage;
var Path = path.split( delimeter );
var fileName = Path[ Path.length - 1 ];
var fileNameLC = fileName.toLowerCase();


Settings.transDur = .8;
Settings.borderWidDW = 1; // Applies to pop-up only when overlay isn't showing

// 2) Controls SS/TN only
Settings.defaultCaption = "";

// 3) Controls SS only settings
Settings.SS = new Array();
Settings.SS.speed = 4.5;
Settings.SS.randomStart = 0;
Settings.SS.audio = 0;
Settings.SS.audioFolder = "";

Settings.TN.align = "center";
Settings.TN.nImagesRow = 8;
Settings.TN.width = 100;
Settings.TN.height = 75;
Settings.TN.AppendSlideShowLink = true;

// Convert original Images array that has dimensions into an array w/o dimensions
var ImagesTemp = new Array();

for( var i = 0; i < Images.length - 1; i++ )
	ImagesTemp.push( [ Images[ i ][ 0 ], Images[ i ][ 3 ].replace( /\^/g, "\"" ) ] );

ImagesTemp.push( null );

Images = ImagesTemp;



///////////////////////////// BEGIN IMAGE LIBRARY FUNCTIONS /////////////////////////////
/*
function checkImgName
function fadeIn
function fadeInDirectX
function getOpacity
function getPhotoCaption
function initImagesArr
function setOpacity
function showImgProperties
function startFade
*/

// Global object that fade will be perfomed on. It is initialized just before fade and set back to null upon completion
FadeObj = null;

// IE Only
transDur = -1;
transDelay = -1;

// MZ, SF & OP Only
fadeOpacity = 0, fadeOpacityTimer = 0, fadeStartTime = 0;
opacityStep = ( window.Settings && window.Settings.SS && Settings.transDur ) ? 1 / ( Settings.transDur / .04 ) : .05;

//--------------- Image Library ---------------

function getOpacity() { return ( IE ) ? "visibility:hidden;" : "opacity:0;"; }

//--------------- Image Library ---------------

function setOpacity( Obj ) { ( IE ) ? Obj.style.visibility = "hidden" : Obj.style.opacity = 0; }

//--------------- Image Library ---------------
// Director: All requests to dissolve are made by calling this function
// Function is thread safe & only one object can be doing a fade at any given time

function startFade( FadeObj, transDur, transDelay ) {

	// If the global FadeObj has not been set then do the fade
	if( window.FadeObj == null ) {

		window.FadeObj = FadeObj;

		if( IE ) {
			window.transDur = transDur;
			window.transDelay = transDelay;
			setTimeout( "fadeInDirectX()", transDelay );
		}
		else {
			fadeStartTime = new Date().getTime();

			FadeObj.onload = function() { /*cancel photo onload function*/ };
			( transDelay ) ? setTimeout( "fadeIn()", transDelay ) : fadeIn();
		}
	}
	// A dissolve is already happening on another object so show this one immediately
	else {
		( IE ) ? FadeObj.style.visibility = "visible" : FadeObj.style.opacity = 1;
		FadeObj.style.visibility = "visible";
	}
}

//--------------- Image Library ---------------
// W3C: Uses recursion so keep this function lean and mean!
// Never call directly, call startFade which then calls this function

function fadeIn() {

	FadeObj.style.opacity = fadeOpacity;
	fadeOpacity += opacityStep;

	if( fadeOpacity < 1 )
		fadeOpacityTimer = setTimeout( "fadeIn();", 40 );
	else {
		FadeObj.style.opacity = 1;
		clearTimeout( fadeOpacityTimer );
		fadeOpacity = 0;
		var fadeEndTime = new Date().getTime();
		var fadeDuration = fadeEndTime - fadeStartTime;
		fadeStartTime = 0;
		if( fadeDuration > 1500 ) opacityStep += .03;
		FadeObj = null;
		//top.document.title = "fadeDuration: " + fadeDuration + "; opacityStep: " + opacityStep; // Save
	}

}

//--------------- Image Library ---------------
// call from startFade only, never call directly
function fadeInDirectX() {
	try {
		FadeObj.style.filter = "progid:DXImageTransform.Microsoft.Fade(duration=" + transDur + ",overlap=1)";
		FadeObj.filters(0).apply();
		FadeObj.style.visibility = "visible";
		FadeObj.filters(0).play();

		// Fires after completion of fade
		FadeObj.onfilterchange = function() { FadeObj = null; }
	}
	catch( Err ) {
		if( local ) {
			var eMsg = "Exception Caught in fadeInDirectX function:\n\n";
			for( var i in Err ) eMsg += i + ": " + Err[ i ] + "\n";
			alert( eMsg );
		}
		FadeObj.style.visibility = "visible";
	}
}

//--------------- Image Library ---------------
// Called by DW image: SS/TN and page enlargements. It manipulates special characters w/i photo caption for display as HTML in DW title bar
// Also applies to tool tips when hovering over thumbnails on TN page

function getPhotoCaption( captionIn ) {

	if( !captionIn ) captionIn = "";
	var captionOut = captionIn.trim();

	if( captionOut ) {

		// Applies to all enlargements
		captionOut = captionOut.replace( /\[/g, "<div class=\"dwTitleLine2\">" ).replace( /]/g, "</div>" );
		captionOut = captionOut.replace( /<>/g, "<span class=\"dwBullet\">&#149;</span>" );
		captionOut = captionOut.replace( /'/g, "&#39;" );
		captionOut = captionOut.replace( /%20/g, " " );
		captionOut = captionOut.replace( /\*/g, Settings.defaultCaption );
	}

	return captionOut;
}

//--------------- Image Library ---------------
// Ensures that Images array is an object & removes null entry at end

function initImagesArr() {
	try {
		if( Images[ Images.length - 1 ] == null ) Images.pop();
	}
	catch( Err ) {
		alert( "Images array cannot be initialized because the data it contains is malformed (bad syntax)" );
	}
}

//--------------- Image Library ---------------
// Admin Only: Writes file-name, dimensions & file-size to DW title bar

function showImgProperties( ThePhoto ) { }
/////////////////////////////// END IMAGE LIBRARY FUNCTIONS ///////////////////////////////

//--------------------------------------------------------------------------------------
// Called from bottom of aspx pages

function pageInit() {


	// If we have a Thumbnails section on this page then place thumbnails within it
	var ThumbnailsGUI = gId( "ThumbnailsGUI" );
	if( ThumbnailsGUI ) {

		// Initialize software
		window.TN = new ThumbNails();

		// Write thumbnails to the page
		TN.displayThumbnails();

		// If a console is present then start progress bar
		var ThumbnailsProgressBar = gId( "ThumbnailsProgressBar" );
		if( ThumbnailsProgressBar )
			TN.updateProgressBar();
	}
}

//--------------------------------------------------------------------------------------
// Called onLoad

function pageLoad() {

	if( window.TN )
		TN.initTN();

}

//--------------------------------------------------------------------------------------

function getAjaxRequest() {

	var Request = null;

	// W3C
	if( window.XMLHttpRequest ) {
		try { Request = new XMLHttpRequest(); }
		catch( Err ) { Request = null; }
	}

	// IE 6-
	else if( window.ActiveXObject ) {
		try { Request = new ActiveXObject( "Msxml2.XMLHTTP" ); }
		catch( Err ) {
			try { Request = new ActiveXObject( "Microsoft.XMLHTTP" ); }
			catch( Err ) { Request = null; }
		}
	}
	return Request;
}

//--------------------------------------------------------------------------------------

/*
	This global AJAX function:
		1. Retrieves slide-show.js file via AJAX request and evaluates it
		2. Starts slide-show via call to DW.createEnlargement
*/

RequestCode = null;

//                 opt       opt   opt
function launchSS( dataFile, Link, nAudio ) {

	if( window.TN ) TN.kill();

	if( !dataFile )
		dataFile = qStr.getVal( "db" );

	if( Link ) {
		var titleOrig = Link.title;
		Link.style.cursor = "wait";
		Link.title = "Starting slide-show, please wait...";
	}

	RequestCode = getAjaxRequest();

	if( RequestCode ) {

		// This function defines what happens upon retrieving the slide-show.js code file
		RequestCode.onreadystatechange = function() {
			try {
				if( RequestCode.readyState == 4 ) {

					// We got the slide-show.js code file...
					if( RequestCode.status == 200 || RequestCode.status == 304 ) {

						// We now have the slide-show code file so evaluate it
						eval( RequestCode.responseText );

						SS = new SlideShow();

						SS.init();

						if( Link ) {
							Link.style.cursor = ( /a/i.test( Link.tagName ) ) ? "pointer" : "default";
							Link.title = titleOrig;
							Link.blur();
						}

						DW.photoCaption = Images[ SS.nFirstSlide ][ 1 ];
						DW.photoCount = SS.getCount( SS.nFirstSlide );

						DW.createEnlargement( "SS", Settings.folder + Images[ SS.nFirstSlide ][ 0 ] );

					}
					else if( RequestCode.status )
						alert( "AJAX error retrieving file \u201Cslide-show.js\u201D at function launchSS\n\nStatus expected: 200 or 304\nStatus returned: " + RequestCode.status );

				}
			}
			catch( Err ) {
				var eMsg = "AJAX exception at function launchSS\n\n";
				for( var i in Err ) eMsg += i + ": " + Err[ i ] + "\n";
				try{ alert( eMsg ); } catch( Err ) { }
			}
		}

		// Get the ss code file
		var cacheBuster = ( local ) ? "?CacheBuster=" + Math.random() : "";
		RequestCode.open( "GET", "Scripts/slide-show.js" + cacheBuster, true );
		RequestCode.send( null );

	}
	else
		alert( "We're sorry, but it seems your browser is unable to make an AJAX (Asynchronous JavaScript And XML) request. As a result, you will not be able to play our slide-show." );

	return false;
}

///////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// DYNAMIC WINDOW DW ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////

function DynamicWindow( transDur ) {

	// Editable Settings
	// These 4 variables apply to IE only and prevent small jerky jump when moving by title bar
	// SS/TN only - where additional table HTML is in title bar.
	this.ssTnskewIeX = 2;
	this.ssTnskewIeY = 6;

	// All other pop-ups (not SS/TN).
	this.skewIeX = 2;
	this.skewIeY = 2;

	// Do not edit past this line -------------------------
	window.gClickPos = null;
	this.transDur = ( transDur ) ? transDur : 0.8;

	// Object variables
	this.dWinOffsetX = 0;
	this.dWinOffsetY = 0;
	this.ImgOffscreen = null;
	this.overlayExists = false;
	this.overTitleBar = false;
	this.Photo = null;
	this.TheBody = null;
	this.Window = null;
	this.winType;

	// Object methods
	this.addOverlay = addOverlay;                                            // function addOverlay
	this.cancelEvt = cancelEvt;                                              // function cancelEvt
	this.cancelPreloader = cancelPreloader;                                  // function cancelPreloader
	this.createEnlargement = createEnlargement;                              // function createEnlargement
	this.getScaledSize = getScaledSize;                                      // function getScaledSize
	this.reCenter = reCenter;                                                // function reCenter
	this.createWindow = createWindow;                                        // function createWindow
	this.showImg = showImg;                                                  // function showImg
	this.keepInWin = keepInWin;                                              // function keepInWin
	this.getClickPosition = getClickPosition;                                // function getClickPosition
	this.getData = getData;                                                  // function getData
	this.mouseDown = mouseDown;                                              // function mouseDown
	this.mouseMove = mouseMove;                                              // function mouseMove
	this.moveTopImage = moveTopImage;                                        // function moveTopImage
	this.otherFunctionalityOnRemoveWin = otherFunctionalityOnRemoveWin;      // function otherFunctionalityOnRemoveWin
	this.removeWin = removeWin;                                              // function removeWin
	this.setBody = setBody;                                                  // function setBody
	this.mouseUp = mouseUp;                                                  // function mouseUp

	document.onmousedown = this.mouseDown;
	document.onmousemove = this.mouseMove;
	document.onmouseup = this.mouseUp;

	var Preloader = new Image(); Preloader.src = "images/preloader.gif";

	//------------------------------------- METHOD DW -------------------------------------
	// To be customized on a per/client basis. Normally set it to null action unless more functionality needed upon closing DW
	function otherFunctionalityOnRemoveWin() { }

	//------------------------------------- METHOD DW -------------------------------------
	// Called by: (1) User clicks "Cancel" while image is loading. (2) Image fails to load via onerror. (3) User clicks X to close.

	function cancelPreloader() {

		var Overlay = gId( "dwOverlay" );
		if( Overlay ) rCh( Overlay );
		this.overlayExists = false;
		this.ImgOffscreen = gId( "ImgOffscreen" );
		if( this.ImgOffscreen ) {
			this.ImgOffscreen.onload = function() { /*cancel function*/ };
			rCh( this.ImgOffscreen );
		}
	}

	//------------------------------------- METHOD DW -------------------------------------
	// Creates and preloads the DW Enlargement off-screen. Upon loading the image is displayed

	function createEnlargement( winType, imgSrc ) {

		DW.addOverlay( 1, winType );

		this.ImgOffscreen = gId( "ImgOffscreen" );
		if( this.ImgOffscreen ) rCh( this.ImgOffscreen );

		this.ImgOffscreen = gEl( "IMG" );
		this.ImgOffscreen.id = "ImgOffscreen";
		this.ImgOffscreen.style.position = "absolute";
		this.ImgOffscreen.style.top = "-1000000px";
		this.ImgOffscreen.style.left = "-1000000px";
		aCh( this.ImgOffscreen );

		// When image loads off-screen show it.
		// To disable (for testing) change to "this.ImgOffscreen.onloadx"
		this.ImgOffscreen.onload = function() {

			// Remove preloader.gif & cancel link from overlay
			var CancelPreload = gId( "CancelPreload" );
			if( CancelPreload ) CancelPreload.innerHTML = "";

			DW.createWindow( [ DW.photoCaption, "imgSrc=" + this.src ], [ 0, this.width, this.height ], null, null, 0, [ 4, 0, 0 ], winType );

			if( winType ) { // SS or TN
				var TdCount = gId( "SsTnCount" );
				TdCount.innerHTML = DW.photoCount;
			}

		}

		// If images fails to load then trap event and notify user of bad file-path
		// To disable (for testing) change to "this.ImgOffscreen.onerrorx"
		this.ImgOffscreen.onerror = function() {
			var imgSrc = this.src;
			DW.cancelPreloader();
			alert( "Image Not Found:\n" + imgSrc );
		}

		// Start pre-loading of off-screen image
		this.ImgOffscreen.src = imgSrc;
	}

	//------------------------------------- METHOD DW -------------------------------------

	//                     1 req    2 req   3 opt    4 opt     5 opt       6 opt         7 opt,   8 opt,            9 opt,  10 opt
	function createWindow( dataSrc, WinDim, TheLink, theEvent, bodyMargin, RequestedPos, winType, centerContent, addOverlay, noX ) {

		this.setBody();

		if( TheLink ) TheLink.blur();

		if( window.SS && winType != "SS" )
			SS.kill();

		if( window.TN && winType != "TN" )
			TN.kill();

		if( !bodyMargin ) bodyMargin = 0;
		this.winType = ( winType ) ? winType : "";

		var Data = this.getData( dataSrc, TheLink ), theCaption, body;

		theCaption = getPhotoCaption( Data[ 0 ] );
		body = Data[ 1 ].replace( /\^\^/g, "'" );
		body = body.replace( /\^/g, "\"" );

		// Read vals from 3-member WindowDimension, if image then get wid/hgt from tag
		var showImg = ( body.indexOf( "imgSrc=" ) == 0 );

		// overflow:auto creates vert scroll bars if content does not fit
		var scrollStyle = ( WinDim[ 0 ] ) ? " overflow:auto;" : "";
		var winWid = WinDim[ 1 ];
		var winHgt = WinDim[ 2 ];

		// Read vals from optional 4-member RequestedPosition
		var clickPos       = ( RequestedPos ) ? ( RequestedPos[ 0 ] == 1 ) : true;
		var aboveClkPos    = ( RequestedPos ) ? ( RequestedPos[ 0 ] == 2 ) : false;
		var topCent        = ( RequestedPos ) ? ( RequestedPos[ 0 ] == 3 ) : false;
		var center         = ( RequestedPos ) ? ( RequestedPos[ 0 ] == 4 ) : false;
		var botCent        = ( RequestedPos ) ? ( RequestedPos[ 0 ] == 5 ) : false;
		var xOffset        = ( RequestedPos ) ? RequestedPos[ 1 ] : 0;
		var yOffset        = ( RequestedPos ) ? RequestedPos[ 2 ] : 15;

		if( showImg ) {

			var imgSrc = body.split( "imgSrc=" )[ 1 ];

			// If image doesn't fit get new scaled down dimensions
			var WinDim = this.getScaledSize( winWid, winHgt, theCaption );
			winWid = WinDim[ 0 ];
			winHgt = WinDim[ 1 ];

			// Create image tag
			var body = "<img src='" + imgSrc + "' border='0' hspace='0' vspace='0' galleryimg='no' style='" + getOpacity() + " width:" + winWid + "px; height:" + winHgt + "px;' onload='DW.showImg( this );' onAbort='this.src=this.src;' id='ImageDW' onmouseover='DW.overImg=true;' onmouseout='DW.overImg=false;'>";

			// Thumbnail
			if( this.winType == "TN" ) {
				var titleBarGUI =
				"<table align='center' id='tnTable'>" +
					"<tr align='center'>" +

						"<td class='dwBackEnlargementSsTn' id='SsTnBackTD' onmousedown='DW.cancelEvt( event );'>" +
							"<a href='javascript:void(0);' onClick='TN.nextImage( 0, event ); return false;' title='Last enlargement' onmousedown='DW.cancelEvt( event );' class='SsTnArrow'>\u25C4</a>" +
						"</td>" +

						"<td class='dwTitle dwImgTitleSS' id='SsTnTitle'>" +
							theCaption +
						"</td>" +

						"<td class='dwNextEnlargementSsTn'>" +
							"<a href='javascript:void(0);' onClick='TN.nextImage( 1, event ); return false;' title='Next enlargement, or click photo...' onmousedown='DW.cancelEvt( event );' class='SsTnArrow' id='SsTnNextArrow'>\u25BA</a>" +
						"</td>" +

					"</tr>" +
				"</table>";
				theCaption = titleBarGUI;

			}
			// Slide-Show
			else if( this.winType == "SS" ) {
				var titleBarGUI =
				"<table align='center' id='tnTable'>" +
					"<tr align='center'>" +

						"<td class='dwBackEnlargementSsTn' id='SsTnBackTD' onmousedown='DW.cancelEvt( event );'>" +
							"<a href='javascript:void(0);' onClick='SS.back(); return false;' title='Back' onmousedown='DW.cancelEvt( event );' class='SsTnArrow'>\u25C4</a>" +
						"</td>" +

						"<td class='dwTitle dwImgTitleSS' id='SsTnTitle'>" +
							theCaption +
						"</td>" +

						"<td class='dwNextEnlargementSsTn'>" +
							"<a href='javascript:void(0);' onClick='SS.next( event ); return false;' title='Next' onmousedown='DW.cancelEvt( event );' class='SsTnArrow' id='SsTnNextArrow'>\u25BA</a>" +
						"</td>" +

					"</tr>" +
				"</table>";
				theCaption = titleBarGUI;

			}

		}

		var Window = gId( "dWinID" );
		if( Window ) rCh( Window );

		var NewWindow = gEl( "DIV" );
		var scrollSt, bodyHgtSt;

		bodyHgtStyle = ( winHgt ) ? " height:" + winHgt + "px;" : "";
		NewWindow.id = "dWinID";
		NewWindow.className = "dwWin";
		aCh( NewWindow );
		NewWindow.style.visibility = "hidden"
		NewWindow.style.position = "absolute";
		var borderWid = ( DW.overlayExists ) ? 0 : Settings.borderWidDW;
		NewWindow.style.borderWidth = borderWid + "px";
		NewWindow.style.width = ( IE && document.compatMode != "CSS1Compat" ) ? ( winWid + ( 2 * borderWid ) ) + "px" : winWid + "px";
		NewWindow.style.top = ( screen.height * -1 ) + "px";
		NewWindow.style.left = ( screen.width * -1 ) + "px";
		NewWindow.style.zIndex = 10000;

		var music = ( this.winType == "SS" && Settings.SS.audio ) ? "&nbsp; &nbsp;<a href='javascript:void(0);' onClick='SS.pause( 1 ); Menu.show( this, \"Menu_Music\", 34, event, 0, 6 );' Menu.keepAlive([\"Menu_Music\"]);' onMouseout='Menu.hide([\"Menu_Music\"]);' class='SsMusic' title='" + Msg.SsAudio + "'>&#9835;</a>&nbsp;" : "";
		var counterCell = ( this.winType == "TN" || this.winType == "SS" ) ? "<td id='dwTitleLeft' class='dwCounterSsTn' onmousedown='DW.cancelEvt( event );'><span id='SsTnCount' onmousedown='DW.cancelEvt( event );'></span><span onmousedown='DW.cancelEvt( event );'>" + music + "</td>" : "";

		var pauseBut = ( this.winType == "SS" ) ? "&nbsp;<a href='javascript:SS.pause( ( SS.running ) ? 1 : 0 );' title='Pause'><img src='images/pauseSsOff.gif' id='PauseSs' class='dwPauseSs' onMouseover='SS.highlightPause( this, 1 );' onMouseout='SS.highlightPause( this, 0 );'></a>&nbsp;" : "";

		var winClass = ( DW.overlayExists || addOverlay ) ? "dwTitleRowOverlay" : "dwTitleRow";

		var dwX = ( noX ) ? "" : "<a href='javascript:DW.removeWin();' title='Close' id='dwX' class='dwX'>&nbsp;&times;&nbsp;</a>";

		var myWindow = "" +

		"<div class='" + winClass + "' id='dwTitleRowID' onmouseover='DW.overTitleBar=true;' onmouseout='DW.overTitleBar=false;'>" +
			"<table align='center'>" +
				"<tr>" +
					counterCell +
					"<td class='dwTitle' style='width:100%; text-align:center;' id='dwTitleCenter'>" +
						theCaption +
					"</td>" +
					"<td valign='top' id='dwTitleRight' onmousedown='DW.cancelEvt( event );' style='white-space:nowrap;'>" +
						pauseBut +
						dwX +
					"</td>" +
				"</tr>" +
			"</table>" +
		"</div>" +

		"<div class='" + ( ( showImg ) ? "dwBodyParentImg" : "dwBodyParent" ) + "' style='width:100%;" + bodyHgtStyle + scrollStyle + "'>" +
			"<div class='dwBody' id='dwBodyID' style='margin:" + bodyMargin + "px;'>";

			if( centerContent )
				myWindow += "<table align='center'><tr><td>";

			myWindow += body;

			if( centerContent )
				myWindow += "</td></tr></table>";

			myWindow +=
			"</div>" +
		"</div>";

		NewWindow.innerHTML = myWindow;
		var xPos = 0, yPos = 0;

		if( clickPos || aboveClkPos ) {

			if( theEvent )
				var ClickPos = this.getClickPosition( theEvent );
			// If null it allows for successive pop-ups to be based on original click position
			else if( window.gClickPos )
				var ClickPos = gClickPos;

			window.gClickPos = ClickPos;

			xPos = ClickPos[ 0 ];
			var vPortWid = ( document.body.clientWidth ) ? document.body.clientWidth : window.innerWidth;
			var skew = Math.round( 100 * xPos / vPortWid ) / 100;
			xPos = xPos + xOffset - ( skew * NewWindow.offsetWidth );

			// 1) Place at click position & add offset (if any)
			if( clickPos )
				yPos = ClickPos[ 1 ] + yOffset;

			// 2) Place above click position & add offset (if any)
			else
				yPos = ClickPos[ 1 ] - NewWindow.offsetHeight + yOffset;

		}

		// 3, 4 or 5) vAlign: Top center (3), Center (4) or Bot Center (5)
		else if( topCent || center || botCent ) {

			var scrollX, scrollY, bodyWid, bodyHgt;

			if( IE ) {
				scrollX = this.TheBody.scrollLeft;
				scrollY = this.TheBody.scrollTop;
				bodyWid = this.TheBody.clientWidth;
				bodyHgt = this.TheBody.clientHeight;
			}
			else {
				scrollX = window.pageXOffset;
				scrollY = window.pageYOffset;
				bodyWid = window.innerWidth;
				bodyHgt = window.innerHeight;
			}

			winHgt = NewWindow.offsetHeight;
			winWid = NewWindow.offsetWidth;

			xPos = parseInt( ( bodyWid - winWid ) / 2 + scrollX + xOffset );
			if( topCent ) yPos = parseInt( scrollY + yOffset );
			else if( center ) yPos = parseInt( ( bodyHgt - winHgt ) / 2 + scrollY + yOffset );
			else yPos = parseInt( bodyHgt - winHgt + scrollY + yOffset );

		}
		else { // RequestedPos[ 0 ] = 10 - 17: Places window around a component

			var Component = ( window.ComponentDW ) ? window.ComponentDW : gId( RequestedPos[ 3 ] );
			if( SF ) { // Defeat Safari bug
				var Target = ( theEvent.target ) ? theEvent.target : theEvent.srcElement;
				if( Target.nodeType == 3 ) Component = Component.parentNode;
			}
			var CurComponent = Component;
			var parPosAbs = false;
			while( CurComponent ) {
				yPos += CurComponent.offsetTop;
				xPos += CurComponent.offsetLeft;
				CurComponent = CurComponent.offsetParent;
			}

			switch( RequestedPos[ 0 ] ) {


				case 10: // above left
					xPos += xOffset;
					yPos -= NewWindow.offsetHeight - yOffset;
					break;

				case 11: // above right
					xPos += Component.offsetWidth + xOffset;
					yPos -= NewWindow.offsetHeight - yOffset;
					break;

				case 12: // right top
					xPos += Component.offsetWidth + xOffset;
					yPos += yOffset;
					break;

				case 13: // right bottom
					xPos += Component.offsetWidth + xOffset;
					yPos += Component.offsetHeight + yOffset;
					break;

				case 14: // below right
					xPos += xOffset;
					yPos += Component.offsetHeight + yOffset;
					break;

				case 15: // below left
					xPos += Component.offsetWidth + xOffset - NewWindow.offsetWidth;
					yPos += Component.offsetHeight + yOffset;
					break;

				case 16: // left below
					xPos += xOffset - NewWindow.offsetWidth;
					yPos += Component.offsetHeight + yOffset;
					break;

				case 17: // left top
					xPos += xOffset - NewWindow.offsetWidth;
					yPos += yOffset;
					break;

				default:
					alert( "Switch/Case Error at DW.createWindow: RequestedPos[ 0 ] has a value of " + RequestedPos[ 0 ] + " which is invalid." );

			}
		}

		var NewWindowPos = this.keepInWin( NewWindow, xPos, yPos );
		xPos = Math.round( NewWindowPos[ 0 ] );
		yPos = Math.round( NewWindowPos[ 1 ] );

		NewWindow.style.left = xPos + "px";
		NewWindow.style.top  = yPos + "px";

		if( addOverlay ) this.addOverlay( 0, winType );

		NewWindow.style.visibility = "visible";

	}
	//------------------------------------- METHOD DW -------------------------------------
	// If enlargement does not fit in viewport this method returns the new scaled down image dimensions.

	function getScaledSize( imgWid, imgHgt, photoCaption ) {

			var photoCaptionLC = photoCaption.toLowerCase();

			// Determine nLines in photo caption.
			var nLines = 1;
			nLines += photoCaptionLC.split( "<div" ).length - 1;
			nLines += photoCaptionLC.split( "<br" ).length - 1;

			var marginX = 45;
			var marginY = 50 + ( 10 * nLines );
			var dwWid = imgWid + marginX;
			var dwHgt = imgHgt + marginY;

			var bodyWid, bodyHgt;
			if( IE ) {
				bodyWid = this.TheBody.clientWidth;
				bodyHgt = this.TheBody.clientHeight;
			}
			else {
				bodyWid = window.innerWidth;
				bodyHgt = window.innerHeight;
			}

			var winWidNew, winHgtNew;

			// Image is too wide or too tall to fit in viewport
			if( dwWid >= bodyWid || dwHgt >= bodyHgt ) {

				var widOver = dwWid - bodyWid;
				var hgtOver = dwHgt - bodyHgt;

				// Height overflow is proportionally greater than width overflow. Scaling down the height ensures that width fits
				if( hgtOver/bodyHgt > widOver/bodyWid ) {
					winHgtNew = bodyHgt - marginY;
					winWidNew = Math.round( ( winHgtNew / imgHgt ) * imgWid );
				}
				// Width overflow is proportionally greater than height overflow. Scaling down the width ensures that height fits
				else {
					winWidNew = bodyWid - marginX;
					winHgtNew = Math.round( ( winWidNew / imgWid ) * imgHgt );
				}
			}
			// Image fits in viewport so return original dimensions
			else {
				winWidNew = imgWid;
				winHgtNew = imgHgt;
			}

			return[ winWidNew, winHgtNew ];

		}

	//------------------------------------- METHOD DW -------------------------------------

	function addOverlay( showPreloader, winType ) {

		this.winType = winType;

		this.setBody();

		var Overlay = gId( "dwOverlay" );
		if( !Overlay  ) {

			// Embedded SS is running so pause it but only when adding overlay
			if( window.SSE && SSE.running ) SSE.pauseSS( 1 );

			// If user scrolls the page then destroy the overlay.
			window.onscroll = function() {
				var Overlay = gId( "dwOverlay" );
				if( Overlay ) {
					rCh( Overlay );
					DW.overlayExists = false;
					// Embedded SS is paused so restart it after removing overlay
					if( window.SSE && !SSE.running ) SSE.pauseSS( 0 );
				}
				if( window.DW ) DW.removeWin();
			}

			var Overlay = gEl( "DIV" );
			Overlay.id = "dwOverlay";
			Overlay.className = "dwOverlay";

			// SS/TN window only
			if( this.winType == "TN" || this.winType == "SS" ) {
				var TopImage = gId( "TopImage" );
				if( TopImage ) {
					rCh( TopImage );
					( this.winType == "SS" ) ? SS.TopImage = null : TN.TopImage = null;
				}
			}
			else {
				Overlay.onclick = function() {
					var CancelPreloadImg = gId( "CancelPreloadImg" );
					if( !CancelPreloadImg ) {
						rCh( this );
						DW.overlayExists = false;
					}
				}
			}

			aCh( Overlay );

			var xPos = ( IE ) ? this.TheBody.scrollLeft : window.pageXOffset;
			var yPos = ( IE ) ? this.TheBody.scrollTop : window.pageYOffset;

			Overlay.style.left  = xPos + "px";
			Overlay.style.top  = yPos + "px";

			if( showPreloader )
				Overlay.innerHTML = "<div align='center' class='cancelPreload' id='CancelPreload'><img src='images/preloader.gif' class='cancelPreload' id='CancelPreloadImg' /><div><a href='javascript:DW.cancelPreloader();' class='cancelPreload' title='Stop image loading'>Cancel</a></div></div>";

		}
		this.overlayExists = true;
	}
	//------------------------------------- METHOD DW -------------------------------------
	// Called by SS/TN windows only - places DW in middle of screen while moving forwards or backwards

	function reCenter( DW ) {

		// Now re-center bottom DW & top image in middle of screen
		var scrollX, scrollY, bodyWid, bodyHgt, xPos, yPos;

		if( IE ) {
			scrollX = this.TheBody.scrollLeft;
			scrollY = this.TheBody.scrollTop;
			bodyWid = this.TheBody.clientWidth;
			bodyHgt = this.TheBody.clientHeight;
		}
		else {
			scrollX = window.pageXOffset;
			scrollY = window.pageYOffset;
			bodyWid = window.innerWidth;
			bodyHgt = window.innerHeight;
		}

		winHgt = DW.offsetHeight;
		winWid = DW.offsetWidth;

		xPos = parseInt( ( bodyWid - winWid ) / 2 + scrollX );
		yPos = parseInt( ( bodyHgt - winHgt ) / 2 + scrollY );

		DW.style.left = xPos + "px";
		DW.style.top  = yPos + "px";
	}

	//------------------------------------- METHOD DW -------------------------------------
	// Called onLoad of image

	function showImg( Photo ) {

		Photo.oncontextmenu = function() { return ( Settings.preventImageTheft ) ? false : true; };

		// On thumbnails page, clicking photo goes to next one
		if( this.winType == "TN" ) {
			Photo.title = "Next enlargement";
			Photo.onclick = function( event ) { TN.nextImage( 1, event ); this.title = ""; }
			gId( "SsTnCount" ).onmouseover = function() {
				var Numbers = this.innerHTML.split( "/" );
				this.title = "Photo #" + Numbers[ 0 ] + " of " + Numbers[ 1 ];
			}
			TN.imgWidOld = Photo.width;
			TN.imgHgtOld = Photo.height;
			TN.preloadNext();
		}
		// On slide-show, clicking photo goes to next one
		else if( this.winType == "SS" ) {
			Photo.title = "Next";
			Photo.onclick = function( event ) { SS.next( event ); this.title = ""; }
			gId( "SsTnCount" ).onmouseover = function() {
				var Numbers = this.innerHTML.split( "/" );
				this.title = "Photo #" + Numbers[ 0 ] + " of " + Numbers[ 1 ];
			}
			SS.imgWidOld = Photo.width;
			SS.imgHgtOld = Photo.height;
			SS.preLoadNext();

		}
		else { // Not a SS or TN window, clicking photo closes it
			Photo.onclick = DW.removeWin;
			Photo.title = "Click to close";
		}

		Photo.style.cursor = "pointer";

		showImgProperties( Photo );
		startFade( Photo, this.transDur, 0 );

	}

	//------------------------------------- METHOD DW -------------------------------------

	function keepInWin( NewWindow, leftEdge, topEdge ) {

		var bodyHgt = ( IE ) ? this.TheBody.clientHeight : window.innerHeight;
		var bodyWid = ( IE ) ? this.TheBody.clientWidth : window.innerWidth;

		// Prevent window from going off bottom & top of page
		var winHgt = NewWindow.offsetHeight;
		var yOffset = ( IE ) ? this.TheBody.scrollTop : window.pageYOffset;
		var vScreenPos = topEdge - yOffset;
		var vSkew = bodyHgt - vScreenPos;
		if( vScreenPos < 10 ) topEdge = 10 + yOffset; // top edge
		else if( vSkew < winHgt + 10 ) topEdge -= winHgt - vSkew + 10; // bottom edge

		// Prevent window from going off right & left edges
		var winWid = NewWindow.offsetWidth;
		var xOffset = ( IE ) ? this.TheBody.scrollLeft : window.pageXOffset;
		var hScreenPos = leftEdge - xOffset;
		var hSkew = bodyWid - hScreenPos;
		if( hScreenPos < 10 ) leftEdge = 10 + xOffset; // left edge
		else if( hSkew < winWid + 10 ) { // right edge
			leftEdge -= winWid - hSkew + 10;
			// Vert scroll bar is present
			if( !IE && this.TheBody.scrollHeight > bodyHgt ) leftEdge -= 15;
		}

		if( leftEdge < 11 ) leftEdge = 10;
		if( topEdge < 11 ) topEdge = 10;

		return[ leftEdge, topEdge ];
	}
	//------------------------------------- METHOD DW -------------------------------------

	function getClickPosition( theEvent ) {

		try {
			if( IE ) {
				var x = event.clientX + this.TheBody.scrollLeft;
				var y = event.clientY + this.TheBody.scrollTop;
			}
			else {
				var x = theEvent.pageX;
				var y = theEvent.pageY;
			}
		}
		// Catch exceptions when action does not create an event, like when
		// creating window from MZ selecting pull-down
		catch( err ) {
			var x = 0;
			var y = 0;
		}

		return[ x, y ];
	}
	//------------------------------------- METHOD DW -------------------------------------

	function getData( dataSrc, TheLink ) {

		// Get the data...
		if( dataSrc == "nextSibling" ) {

			// If we have old innerHTML then put it back where it belongs
			if( eval( "typeof this.LastSrc" ) == "object" )
				eval( "this.LastSrc.innerHTML = this.lastData" );

			try {
				var DataSource = ( TheLink.nextSibling.innerHTML ) ? TheLink.nextSibling : TheLink.nextSibling.nextSibling;
			}
			catch( err ) { alert( "EXCEPTION: Data source not found" ); return false; }

			try {
				var Title = ( DataSource.firstChild.innerHTML ) ? DataSource.firstChild : DataSource.firstChild.nextSibling;
				var title = Title.innerHTML;
			}
			catch( err ) { alert( "EXCEPTION: Title source not found" ); return false; }

			try {
				var Body = ( Title.nextSibling.innerHTML ) ? Title.nextSibling : Title.nextSibling.nextSibling;
				var body = Body.innerHTML;
			}
			catch( err ) { alert( "EXCEPTION: Body source not found" ); return false; }

			// Record this Source as Object & record innerHTML
			eval( "this.LastSrc = DataSource" );
			eval( "this.lastData = DataSource.innerHTML" );
			DataSource.innerHTML = "";

		}
		else {
			var title = dataSrc[ 0 ];
			var body  = dataSrc[ 1 ];
		}

		return[ title, body ];

	}

	//------------------------------------- METHOD DW -------------------------------------
	// Record x & y offset within dWin and set this.Window
	function mouseDown( e ) {

		if( DW.overTitleBar ) {

			document.onmousedown = DW.mouseDown;
			document.onmousemove = DW.mouseMove;
			document.onmouseup = DW.mouseUp;

			this.Window = gId( "dWinID" );

			if( IE ) {

				var borderWid = ( DW.overlayExists ) ? 0 : Settings.borderWidDW;

				// IE jumps radically when moving with other html in title bar, this prevents that jerky movement
				if( DW.winType == "TN" || DW.winType == "SS" ) {

					this.dWinOffsetX = event.offsetX + borderWid + DW.ssTnskewIeX;
					this.dWinOffsetY = event.offsetY + borderWid + DW.ssTnskewIeY;
					var Elem = event.srcElement, ParentElem = Elem.offsetParent;

					if( Elem.id == "dwTitleCenter" )
						this.dWinOffsetX += gId( "dwTitleLeft" ).scrollWidth;

					else if( Elem.id == "SsTnTitle" || ParentElem.id == "SsTnTitle" ) {
						var CurComponent = Elem;
						var xPos = 0, yPos = 0;
						while( CurComponent ) {
							if( CurComponent.id == "tnTable" ) {
								yPos = CurComponent.offsetTop;
								xPos = CurComponent.offsetLeft;
								break;
							}
							CurComponent = CurComponent.offsetParent;
						}
						this.dWinOffsetX += gId( "dwTitleLeft" ).scrollWidth + gId( "SsTnBackTD" ).scrollWidth + xPos;

					}

					else if( Elem.id == "dwTitleRight" ) {
						var CurComponent = Elem;
						var xPos = 0, yPos = 0;
						while( CurComponent ) {
							if( CurComponent.id == "dwTitleRight" ) {
								yPos = CurComponent.offsetTop;
								xPos = CurComponent.offsetLeft;
								break;
							}
							CurComponent = CurComponent.offsetParent;
						}
						this.dWinOffsetX += xPos;
					}
				}
				else { // Not a SS/TN pop-up
					this.dWinOffsetX = event.offsetX + borderWid + DW.skewIeX;
					this.dWinOffsetY = event.offsetY + borderWid + DW.skewIeY;
				}
			}
			else {
				this.dWinOffsetX = e.layerX;
				this.dWinOffsetY = e.layerY;
				return false;
			}
		}
		else if( DW.overImg && Settings.preventImageTheft ) {
			document.onmousemove = function() { return false; }
			document.onmouseup = function() { return false; }
			return false;
		}
	}

	//------------------------------------- METHOD DW -------------------------------------

	function mouseMove( e ) {

		if( this.Window && !OP ) {

			var ClickPos = DW.getClickPosition( e );

			// Don't let user move window off left or top edge of screen
			if( ClickPos[ 0 ] <= 0 ||  ClickPos[ 1 ] <= 0 ) {
				this.Window = null;
				return false;
			}

			if( IE ) {
				if( event.button != 1 ) return false; // mouse moved off screen
				this.Window.style.left = ( event.clientX - this.dWinOffsetX + DW.TheBody.scrollLeft ) + "px";
				this.Window.style.top = ( event.clientY - this.dWinOffsetY + DW.TheBody.scrollTop ) + "px";
				DW.moveTopImage();
				return false;
			}

			else {
				this.Window.style.top = ( e.pageY - this.dWinOffsetY ) + "px";
				this.Window.style.left = ( e.pageX - this.dWinOffsetX ) + "px";
				DW.moveTopImage();
			}

		}
	}

	//------------------------------------- METHOD DW -------------------------------------

	// called by x only or clicking photo. Do not remove inner HTML by setting it to an empty string
	function removeWin() {
		var EvalOnClose = gId( "EvalOnClose" );
		if( EvalOnClose ) eval( EvalOnClose.value );
		var Window = gId( "dWinID" );
		if( Window ) rCh( Window );
		DW.cancelPreloader();
		// Embedded SS is paused so restart it upon closing DW
		if( window.SSE && !SSE.running ) SSE.pauseSS( 0 );
		DW.overTitleBar = false;
		switch( DW.winType ) {
			case "SS": if( window.SS ) SS.kill();	break;
			case "TN": if( window.TN ) TN.kill(); break;
		}
		DW.otherFunctionalityOnRemoveWin();

	}

	//------------------------------------- METHOD DW -------------------------------------
	// Called by SS/TN windows only - places top image (if any) precisely on top of bottom image

	function moveTopImage() {

		var TopImage = gId( "TopImage" );
		if( TopImage ) {
			var BotImage = gId( "ImageDW" );

			// Get on screen position of bottom image so we can lay new one on top
			var x = 0; var y = 0;
			TheElement = BotImage;
			var parPosAbs = false;
			while( TheElement ) {
				if( SF ) {
					if( !parPosAbs ) parPosAbs = ( TheElement.style.position == "absolute" );
					if( parPosAbs && TheElement == document.body ) break;
				}
				y += TheElement.offsetTop;
				x += TheElement.offsetLeft;
				TheElement = TheElement.offsetParent;
			}

			var borderWid = ( DW.overlayExists || OP ) ? 0 : Settings.borderWidDW;

			// Cannot read css defined border-width with script, that's why we must use Settings.borderWidDW
			TopImage.style.left = ( x + borderWid - parseInt( BotImage.parentNode.style.marginLeft ) ) + "px";
			TopImage.style.top  = ( y + borderWid - parseInt( BotImage.parentNode.style.marginTop  ) ) + "px";
		}
	}
	//------------------------------------- METHOD DW -------------------------------------

	function mouseUp() { this.Window = null; }

	//------------------------------------- METHOD DW -------------------------------------

	function setBody() {
		if( !this.TheBody )
			this.TheBody = ( document.compatMode && document.compatMode != "BackCompat" ) ? document.documentElement : document.body;
	}

	//------------------------------------- METHOD DW -------------------------------------

	function cancelEvt( evt ) {

		( evt && evt.stopPropagation ) ? evt.stopPropagation() : event.cancelBubble = true;

	}

	//------------------------------------- METHOD DW -------------------------------------

}

DW = new DynamicWindow();

////////////////////////////////// END DYNAMIC WINDOW //////////////////////////////////


//////////////////////////////////////// START THUMBNAILS: TN ///////////////////////////////////////

function ThumbNails() {

	initImagesArr();

	// Object variables
	this.dissolve = true;
	this.NextLgImage = null;
	this.OldImage = null;
	this.nextImgTimer = 0;
	this.progressBarTimer = 0;
	this.curIndex = -1;
	this.tnRemainingTN = 0;
	this.TheBody = null;
	this.TopImage = null;
	this.imgWidOld = 0;
	this.imgHgtOld = 0;


	// Object methods
	this.checkTnDim = checkTnDim;                                  // function checkTnDim
	this.displayThumbnails = displayThumbnails;                    // function displayThumbnails
	this.enlarge = enlarge;                                        // function enlarge
	this.getCount = getCount;                                      // function getCount
	this.getNewIndex = getNewIndex;                                // function getNewIndex
	this.getThumbnails = getThumbnails;                            // function getThumbnails
	this.imgBorder = imgBorder;                                    // function imgBorder
	this.init = init;                                              // function init
	this.init(); // Call init immediately
	this.initTN = initTN;                                          // function initTN
	this.kill = kill;                                              // function kill
	this.nextImage = nextImage;                                    // function nextImage
	this.preloadNext = preloadNext;                                // function preloadNext
	this.showDownloadProgress = showDownloadProgress;              // function showDownloadProgress
	this.showNumImages = showNumImages;                            // function showNumImages
	this.updateProgressBar = updateProgressBar;                    // function updateProgressBar


	//------------------------------------- METHOD TN -------------------------------------

	function displayThumbnails() {
		gId( "ThumbnailsGUI" ).innerHTML = TN.getThumbnails();
	}

	//------------------------------------- METHOD TN -------------------------------------
	// Called upon initialization of ThumbNails & after administrator publishes at FW.publishImageEditor

	function init() {
		this.nImages = Images.length;
		this.maxIndex = this.nImages - 1;
		this.ImagesOriginal = Images;
		this.folderOriginal = Settings.folder;
		this.defaultCaption = Settings.defaultCaption;
	}

	//------------------------------------- METHOD TN -------------------------------------
	// Called onLoad of TN page

	function initTN() {
		this.showNumImages();
		this.checkTnDim();
	}
	//------------------------------------- METHOD TN -------------------------------------
	// Returns newIndex: This next image value is based on value of global TN.curIndex
	function getNewIndex( movingForward ) {

		if( movingForward )
			return ( this.curIndex < this.maxIndex ) ? this.curIndex + 1 : 0;
		else
			return ( this.curIndex > 0 ) ? this.curIndex - 1 : this.maxIndex;

	}

	//------------------------------------- METHOD TN -------------------------------------
	// Called onLoad of large Image

	function preloadNext() {
		var newIndex = this.getNewIndex( 1 );
		var PreLoadImage = new Image();
		PreLoadImage.src = Settings.folder + Images[ newIndex ][ 0 ];
		var nOldImg = ( newIndex == 0 ) ? Images.length - 1 : newIndex - 1;
		this.OldImage = new Image();
		this.OldImage.src = Settings.folder + Images[ nOldImg ][ 0 ];
	}

	//------------------------------------- METHOD TN -------------------------------------
	function imgBorder( Img, color ) { if( Img.complete ) Img.style.borderColor = color; }

	//------------------------------------- METHOD TN -------------------------------------
	// Called onLoad of TN page by TN.initTN

	function showNumImages() {
		var ThumbnailsProgressBar = gId( "ThumbnailsProgressBar" );
		if( ThumbnailsProgressBar && this.nImages > -1 ) {
			if( Settings.TN.ProgressBar.hideOnSuccess )
				ThumbnailsProgressBar.style.visibility = "hidden";
		}
	}
	//------------------------------------- METHOD TN -------------------------------------


	function updateProgressBar() {

		var ThumbnailsProgressBar = gId( "ThumbnailsProgressBar" );

		try {
			if( this.tnRemainingTN >= 0 ) {
				var dBarWid = ( this.nImages - this.tnRemainingTN ) * ( Settings.TN.ProgressBar.width / this.nImages );
				var percentLoaded = parseInt( ( ( this.nImages - this.tnRemainingTN ) / this.nImages ) * 100 );

				if( !Settings.TN.ProgressBar.hideOnSuccess ) {
					dBarWid = this.nImages / 2 * ( Settings.TN.ProgressBar.width / this.nImages );
					percentLoaded = 50;
				}

				var Pbar = new Array( 21 );
				Pbar.push( "<div style='width:" );
				Pbar.push( Settings.TN.ProgressBar.width );
				Pbar.push( "px; background-color:" );
				Pbar.push( Settings.TN.ProgressBar.bgColor );
				Pbar.push( "; text-align:left; z-index:0;'>" );
				Pbar.push( "<div style='width:" );
				Pbar.push( dBarWid );
				Pbar.push( "px; background-color:" );
				Pbar.push( Settings.TN.ProgressBar.progressColor );
				Pbar.push( ";'>" );
				Pbar.push( "&nbsp;" );
				Pbar.push( "</div>" );
				Pbar.push( "</div>" );
				Pbar.push( "<div style='position:relative; top:-14px; left:0px; width:" );
				Pbar.push( Settings.TN.ProgressBar.width );
				Pbar.push( "px; text-align:center; z-index:1; font-family:arial,helvetica; font-size:8pt; color:" );
				Pbar.push( Settings.TN.ProgressBar.fontColor );
				Pbar.push( "; font-weight:bold;'>" );
				Pbar.push( percentLoaded );
				Pbar.push( "%" );
				Pbar.push( "</div>" );
				ThumbnailsProgressBar.innerHTML = Pbar.join( "" );
				if( !Settings.TN.ProgressBar.hideOnSuccess )
					clearTimeout( TN.progressBarTimer );
				else if( this.tnRemainingTN > 0 ) TN.progressBarTimer = setTimeout( "TN.updateProgressBar()", 200 );
				else if( Settings.TN.ProgressBar.hideOnSuccess ) ThumbnailsProgressBar.style.visibility = "hidden";
			}
		}
		catch( Err ) {
			TN.progressBarTimer = setTimeout( "TN.updateProgressBar()", 250 );
		}
	}

	//------------------------------------- METHOD TN -------------------------------------
	// Returns photo-caption as a string (ex: 2/24)

	function getCount( newIndex ) { return ( newIndex + 1 ) + "/" + ( this.maxIndex + 1 ); }

	//------------------------------------ METHOD TN ------------------------------------

	function kill() {
		this.NextLgImage = null;
		clearInterval( this.nextImgTimer );
		this.nextImgTimer = 0;
		if( this.TopImage ) {
			rCh( this.TopImage );
			this.TopImage = null;
		}
	}

	//------------------------------------- METHOD TN -------------------------------------
	// Called only when user clicks back "<<" & forward ">>" links on enlargement

	function nextImage( movingForward, evt ) {

		var ImageDW = gId( "ImageDW" );
		if( ImageDW ) {

			var newIndex = this.getNewIndex( movingForward );
			if( !this.NextLgImage ) {
				this.NextLgImage = new Image();
				this.NextLgImage.src = Settings.folder + Images[ newIndex ][ 0 ];
			}

			if( this.NextLgImage.complete && this.OldImage.complete ) {

				if( !evt ) evt = window.event;

				if( evt && evt.shiftKey ) this.dissolve = false;

				if( !gId( "dwOverlay" ) )
					DW.addOverlay( 0, "TN" );

				ImageDW.onload = null;

				// Get dimensions of new images
				var imgWidNew = this.NextLgImage.width;
				var imgHgtNew = this.NextLgImage.height;

				// If image doesn't fit get new scaled down dimensions
				var WinDim = DW.getScaledSize( imgWidNew, imgHgtNew, Images[ newIndex ][ 1 ] );
				imgWidNew = WinDim[ 0 ];
				imgHgtNew = WinDim[ 1 ];

				// Create top div tag that will contain new image
				if( !TN.TopImage ) {
					TN.TopImage = gEl( "IMG" );
					TN.TopImage.id = "TopImage";
					TN.TopImage.style.top = ( imgHgtNew * -2 ) + "px";
					TN.TopImage.style.left = ( imgWidNew * -2 ) + "px";
					TN.TopImage.style.zIndex = 10001;
					TN.TopImage.style.position = "absolute";
					TN.TopImage.style.cursor = "pointer";
					TN.TopImage.oncontextmenu = function() { return ( Settings.preventImageTheft ) ? false : true; }
					TN.TopImage.onmouseover = function() { DW.overImg = true; }
					TN.TopImage.onmouseout = function() { DW.overImg = false; }
					TN.TopImage.onclick = function( event ) {
						TN.nextImage( 1, event );
						this.title = "Next enlargement";
						gId( "ImageDW" ).title = "";
					}
					aCh( TN.TopImage );
				}

				TN.TopImage.title = "Next enlargement";

				// Make top image transparent
				( IE ) ? TN.TopImage.style.visibility = "hidden" : TN.TopImage.style.opacity = 0;

				// Apply src & dimensions to top image
				TN.TopImage.src = this.NextLgImage.src;
				TN.TopImage.style.height = imgHgtNew + "px";
				TN.TopImage.style.width = imgWidNew + "px";

				// Top image is prepared and ready to be faded into view, so prep bottom image & DW...
				var Win = gId( "dWinID" );

				// Update title-bar
				gId( "SsTnCount" ).innerHTML = this.getCount( newIndex );

				var photoCaption = getPhotoCaption( Images[ newIndex ][ 1 ] );
				gId( "SsTnTitle" ).innerHTML = photoCaption;

				// Set styles & src of bottom DW & Image
				var marLeft = Math.round( ( imgWidNew - this.imgWidOld ) / 2 );
				var marTop = Math.round( ( imgHgtNew - this.imgHgtOld ) / 2 );
				ImageDW.parentNode.style.marginLeft = marLeft + "px";
				ImageDW.parentNode.style.marginTop = marTop + "px";
				ImageDW.parentNode.parentNode.style.overflow = "hidden";
				ImageDW.src = this.OldImage.src;
				ImageDW.style.width =  this.imgWidOld + "px";
				ImageDW.style.height = this.imgHgtOld + "px";

				// Record dimensions of bottom (old) image
				this.imgWidOld = imgWidNew;
				this.imgHgtOld = imgHgtNew;

				// Set window size to match image size
				// Set height of div class="dwBodyParentImg" to that of its image
				ImageDW.parentNode.parentNode.style.height = imgHgtNew + "px";
				Win.style.width = imgWidNew + "px";

				// Re-center DW
				DW.reCenter( Win );

				// Move top div with image into position - place exactly above old image
				DW.moveTopImage();

				this.NextLgImage = null;
				clearInterval( this.nextImgTimer );
				this.nextImgTimer = 0;

				// curIndex is initially established onClick of any thumbnail, and then incremented/decremented here only
				// All other occurences of this variable are for "read-only" access to it's value
				this.curIndex = ( movingForward ) ? this.curIndex + 1 : this.curIndex - 1;
				if( this.curIndex > this.maxIndex )
					this.curIndex = 0;
				else if( this.curIndex < 0 )
					this.curIndex = this.maxIndex;

				this.preloadNext();

				showImgProperties( TN.TopImage );

				if( this.dissolve )
					startFade( TN.TopImage, Settings.transDur, 0 );
				else {
					( IE ) ? TN.TopImage.style.visibility = "visible" : TN.TopImage.style.opacity = 1;
					TN.TopImage.style.visibility = "visible";
				}
				this.dissolve = true;
			}
			else { // Next image still loading

				// If stmt prevents multiple threads running this method concurrently, which setInterval would allow
				if( this.nextImgTimer == 0 ) {
					eval( "this.nextImgTimer = setInterval( 'TN.nextImage( " + movingForward + " )', 250 );" ); // 250
					gId( "SsTnTitle" ).innerHTML = "Downloading Image<span id='dot1'>.</span><span id='dot2'>.</span><span id='dot3'>.</span><span id='dot4'>.</span>";
					this.showDownloadProgress();
				}
			}
		}
		else // Image not present, like when user closes photo, if thread is running this kills it
			this.kill();
	}

	//--------------------------------------------------------------------------------------
	// Called when user requests next image and it is still loading

	var nDotsVisible = 4;

	function showDownloadProgress() {

		var Dot1 = gId( "dot1" );
		var Dot2 = gId( "dot2" );
		var Dot3 = gId( "dot3" );
		var Dot4 = gId( "dot4" );

		// Make sure dots are visible, as they get replaced by caption when image loads
		if( Dot1 && Dot2 && Dot3 && Dot4 ) {

			for( var i = 1; i <= 4; i++ )
				gId( "dot" + i ).style.visibility = ( i <= nDotsVisible ) ?  "visible" : "hidden";

			nDotsVisible++;
			if( nDotsVisible == 5 ) nDotsVisible = 0;

			setTimeout( "TN.showDownloadProgress();", 500 );
		}
	}


	//--------------------------------------------------------------------------------------
	// Called when user clicks on thumbnail

	function enlarge( cap, imageNum ) {

		if( window.SS ) SS.kill();

		this.TheBody = ( document.compatMode && document.compatMode != "BackCompat" ) ? document.documentElement : document.body;

		// Images array could be referencing the wrong data. Happens if user plays a different SS while on this TN page
		// Closing SS sets window.Images to null and here's the chance to reset settings

		if( window.Images == null ) {
			window.Images = this.ImagesOriginal;
			Settings.folder = this.folderOriginal;
			Settings.defaultCaption = this.defaultCaption;
		}

		DW.photoCaption = Images[ imageNum ][ 1 ];
		DW.photoCount = TN.getCount( imageNum );

		DW.createEnlargement( "TN", Settings.folder + Images[ imageNum ][ 0 ] );

		return false;
	}
	//------------------------------------- METHOD TN -------------------------------------

	function getThumbnails() {

		this.tnRemainingTN = this.nImages;

		var Htm = new Array();

		var tnNum = 0;

		thePageTitle = Settings.TN.pageTitle;
		thePageTitle = thePageTitle.replace( /\^\^/g, "&#39;" );
		thePageTitle = thePageTitle.replace( /\^/g, "&#34;" );

		if( thePageTitle ) {
			Htm.push( "<div class='tnTitle' align='center'>" );
			Htm.push( thePageTitle );
			if( Settings.TN.AppendSlideShowLink ) {
				Htm.push( "<span class='bullet'>&#149;</span><a href='javascript:void(0);' onClick='return launchSS( null, this );' class='SlideShowLink' title='View these photos in a slide-show'>Run Slide-Show</a>" );
			}
			Htm.push( "</div>" );
		}

		var cls = "tnPage";

		Htm.push( "<table align='center'>" );

		var nRows = Math.floor( this.nImages / Settings.TN.nImagesRow ) + 1;

		///////////////// START ROWS /////////////////
		for( var row = 0; row < nRows; row++ ) {

			Htm.push( "<tr align='" ); Htm.push( Settings.TN.align ); Htm.push( "' valign='middle'><td align='center' style='white-space:nowrap;'>" );
			Htm.push( "<table align='center'>" );
			Htm.push( "<tr>" );

			///////////////// START TNs /////////////////
			for( var i = 0; i < Settings.TN.nImagesRow; i++ ) {

				var thisTnImgData = '';
				var writeTN = ( tnNum < this.nImages ) ? true : false;

				if( writeTN ) {

					// Create tnImageName from large image name
					var lgImageName = Images[ tnNum ][ 0 ], tnImageName = "";
					lastDotPos = lgImageName.lastIndexOf( "." );
					var fileExt = "TN" + lgImageName.substring( lastDotPos, lgImageName.length );
					// If optional 2nd member dictating other TN to use is present then use that instead...
					tnImageName = ( Images[ tnNum ][ 2 ] ) ? Images[ tnNum ][ 2 ] : lgImageName.split( "." )[ 0 ] + fileExt;

					var imgTitle = Images[ tnNum ][ 1 ];
					imgTitle = imgTitle.replace( /'/g, "&#39;" );
					imgTitle = imgTitle.replace( /\"/g, "" );
					imgTitle = imgTitle.replace( /"/g, "\\\"" );

					// Swap <> w/ bullet
					var toolTip = imgTitle.replace( /<>/g, " &#149; " );

					// Remove HTML tags
					toolTip = toolTip.replace( /<.*?>/g, " " );

					// Replace asterisk with default photo caption
					toolTip = toolTip.replace( /\*/g, Settings.defaultCaption );

					// Remove brackets & 2+ extra white spaces
					toolTip = toolTip.replace( /\[/g, ", " ).replace( /\]/g, "" ).replace( / {2,}/g, " " );

					var tn = Settings.folder + tnImageName;
					tnNum++;
				}

				var imageNum = row * Settings.TN.nImagesRow + i + 1;

				if( writeTN ) {

					var lgImgName = Images[ tnNum - 1 ][ 0 ];

					var toolTipColon = ( toolTip ) ? ": " : "";
					toolTip = imageNum + "/" + this.nImages + toolTipColon + toolTip;

					Htm.push( "<td class='" );
					Htm.push( cls );
					Htm.push( "'>" );
					Htm.push( "<a href='javascript:void(0);' title=\"" );
					Htm.push( toolTip );
					Htm.push( "\" onClick='if( window.DW ) { TN.curIndex = " );
					Htm.push( imageNum - 1 );
					Htm.push( "; this.blur(); return TN.enlarge( \"" );
					Htm.push( imgTitle );
					Htm.push( "\", " );
					Htm.push( imageNum - 1 );
					Htm.push( " ); }'>" );

					Htm.push( "<img src='" );
					Htm.push( tn );
					Htm.push( "'" );
					Htm.push( " title=\"" );
					Htm.push( toolTip );
					Htm.push( "\" " );
					Htm.push( "class='" );
					Htm.push( cls );
					Htm.push( "' style='" );
					Htm.push( "border-color:" ); Htm.push( Settings.TN.borderColorOff ); Htm.push( ";" );
					Htm.push( " width:" ); Htm.push( Settings.TN.width ); Htm.push( "px;" );
					Htm.push( " height:" ); Htm.push( Settings.TN.height ); Htm.push( "px;" );
					Htm.push( "'" );
					Htm.push( " onMouseover='if( window.TN ) TN.imgBorder(this,Settings.TN.borderColorOn);' onMouseout='if( window.TN ) TN.imgBorder(this,Settings.TN.borderColorOff);' onAbort='this.src=this.src;' onLoad='TN.tnRemainingTN--;' onContextMenu='" );
					Htm.push( ( ( Settings.preventImageTheft ) ? "return false;" : "return true;" ) );
					Htm.push( "' id='TN_" );
					Htm.push( imageNum );
					Htm.push( "'>" );

					Htm.push( "</a>" );
					Htm.push( "</td>" );
				}

			}
			///////////////// END TNs /////////////////

			Htm.push( "</tr>" );
			Htm.push( "</table>" );
			Htm.push( "</td></tr>" );


		///////////////// END ROWS /////////////////

		}

		Htm.push( "</table>" );

		if( Settings.TN.AppendSlideShowLink ) {
			Htm.push( "<div align='center' class='SlideShowLink'>" );
				Htm.push( "<a href='javascript:void(0);' onClick='return launchSS( null, this );' class='SlideShowLink' title='View these photos in a slide-show'>Run Slide-Show</a>" );
			Htm.push( "</div>" );
		}

		var htm = Htm.join( "" );
		return htm;

	}

	//------------------------------------- METHOD TN -------------------------------------
	// Check tn dimensions - admin mode only

	this.checkTN = 1; this.checkTnTimer = 0; this.TnReal = null; this.TnSizeErr = "";
	function checkTnDim() { }
} //////////////////////////////////////// END THUMBNAILS: TN ///////////////////////////////////////

