/*

------------
Installation
------------

Call jaxSlideshowRegister() during your document's onLoad() event to add a 
slideshow to your document.  The slideshow will be appended to the element 
specified by you, and will bear dimensions + look and feel as described by 
the jax-slideshow.css file.  Some steps you'll need to follow to get it working:

	1) include jax-slideshow.js in your html (via <script> tag),
	2) include common/jax-xmlhttprequest.js  in your html (via <script> tag),
	3) include the contents of jax-slideshow.css in your html or other css 
	   file (via <style> or <link> tags),
	4) in the body of your html have a tag with an id (preferably a <div> tag),
	5) call jaxSlideshowRegister() on document load,
	6) write a server-side response script that gathers stored content (like
	   from a database) and returns it.

Parameter descriptions for jaxSlideshowRegister():

	contentURL: url that returns an xml feed to populate the slideshow
	id:         id of the element (preferably div) to append slideshow to
	
-------
Credits
-------

Authored by Dan Juliano in August of 2006.

*/

var ssParent   = null;
var ssFooter   = null;
var ssPrime    = null;
var ssSlide    = null;
var ssTitles   = null;
var ssPaths    = null;
var ssImages   = null;
var ssIndex    = 0;
var ssCenter   = null;
var ssCounter  = 0;

var ssWaitForFooter        = 500;
var ssWaitFirstSlide       = 1000;
var ssWaitForNewSlide      = 3000;
var ssWaitFooterHold       = 1500;
var ssWaitOpacityIncrement = 100;

var ssEnableModal = false;

function jaxSlideshowRegister(url, id, enableModal) {
	jaxSlideshowBuild(id, enableModal);
	xmlRequest(url, null, jaxSlideshowHandleXML);
}

function jaxSlideshowBuild(id, enableModal) {
	
	// Slideshow is a simple set of div layers.  The footer will 
	// display on top of the main layer, and will incrementally 
	// fade out.
	var html = "\n\n";
	html += "<div id='slideshow_main'>\n";
	html += "\t<div id='slideshow_footer'></div>\n";
	html += "\t<div id='slideshow_loading'>Loading</div>\n";
	html += "\t<img id='slideshow_prime' src='' style='position: absolute; visibility: hidden; display: none;' />\n";
	html += "\t<img id='slideshow_slide' src='' style='position: absolute; visibility: hidden; display: none;' />\n";
	html += "</div>\n\n";
	document.getElementById(id).innerHTML = html;
	
	// Initialize global vars for main slide and footer.
	ssParent = document.getElementById("slideshow_main");
	ssFooter = document.getElementById("slideshow_footer");
	ssPrime = document.getElementById("slideshow_prime");
	ssSlide = document.getElementById("slideshow_slide");
	
	ssFooter.style.top = (ssParent.clientHeight - ssFooter.clientHeight) + "px";
	jaxCommonLoadingMessageReset("slideshow_loading", "slideshow_main");
	
	if (enableModal) {
		jaxModalInitialize();
		ssEnableModal = true;
	}
}

function jaxSlideshowHandleXML(xml) {
	
	// Transfer xml to arrays.
	var titles = xml.getElementsByTagName("title");
	var paths = xml.getElementsByTagName("path");
	var length = titles.length;
	
	if (length == 0) {
		document.getElementById('slideshow_loading').innerHTML = 'No Images To Display';
		return;
	}
	
	// Transfer to global arrays, useful for processing the footer bar.
	ssTitles = new Array(length);
	ssPaths = new Array(length);
	ssImages = new Array(length);
	for (var i = 0; i < titles.length; i++) {
		ssTitles[i] = titles[i].firstChild.nodeValue;
		ssPaths[i]  = paths[i].firstChild.nodeValue;
		ssImages[i] = jaxSlideshowImagePreload(ssPaths[i]);
	}
	
	// Make the loading message go away.
	jaxCommonLoadingMessageHide("slideshow_loading");
	
	if (ssEnableModal) {
		var mainSlide = document.getElementById('slideshow_main');
		mainSlide.style.cursor = 'pointer';
		mainSlide.onclick = function(){
			jaxModelOpen(jaxSlideshowDrawFullsizeGallery);
		};
	}
	
	jaxSlideshowStartShow();
}

function jaxSlideshowImagePreload(src) {
	var element = null;
	element = document.createElement('img');
	element.src = src;
	element.style.visibility = 'hidden';
	element.style.position   = 'absolute';
	document.body.appendChild(element);
	return element;
}

function jaxSlideshowDebugImages(){
	messages = [];
	for (var i = 0; i < ssImages.length; i++) {
		messages[messages.length] = 'index: ' + i;
		messages[messages.length] = 'height: ' + ssImages[i].height;
		messages[messages.length] = 'width: ' + ssImages[i].width;
	}
	debug(messages);
}

function jaxSlideshowStartShow() {

	// Don't load the first image until the browser knows its dimensions.
	// This prevents funny visual artifacts.
	if (jaxSlideshowImageNotYetLoaded(0)) {
		ssImages[0].timer = setTimeout('jaxSlideshowStartShow()', 1000);
		ssCounter++;
		return;
	}
	
	// Initialize show to first image.
	ssPrime.src = ssPaths[0];
	ssPrime.style.display = "block";
	jaxSlideshowComputeSizeAndPosition(ssPrime, 0);

	// Initialize secondary slide.
	ssSlide.src = ssPrime.src;
	ssSlide.style.opacity = 0;
	ssSlide.style.display = "block";
	ssSlide.visibility = "visible";
	jaxSlideshowComputeSizeAndPosition(ssSlide, 0);
	
	setTimeout('jaxSlideshowNextSlide()', ssWaitFirstSlide);
}

function jaxSlideshowImageNotYetLoaded(index) {
	if (index >= ssImages.length) return false;
	if (ssImages[index].height == null) return true;
	if (ssImages[index].height == 0) return true;
	if (ssImages[index].width == null) return true;
	if (ssImages[index].width == 0) return true;
	return false;
}

function jaxSlideshowComputeSizeAndPosition(slide, index) {
	
	var heightImage  = ssImages[index].height;
	var heightParent = ssParent.clientHeight;
	var heightCenter = heightParent / 2;
	
	var widthImage  = ssImages[index].clientWidth;
	var widthParent = ssParent.clientWidth;
	var widthCenter = widthParent / 2;
	
	var ratioParent = heightParent / widthParent;
	var ratioImage  = heightImage / widthImage;
	
	var top      = 0;
	var left     = 0;
	var adjusted = 0;
	var path     = 0;

	// The difference in ratios determines whether we crop the top and bottom
	// or sides of the slide when viewing inside the parent container.
	if (ratioParent >= ratioImage) {
		// Image has more width by ratio than slide, so crop top and bottom
		path         = 1;
		slide.width  = widthParent;
		adjusted     = slide.width * (heightImage / widthImage);
		slide.height = adjusted;
		
		top = (heightParent - adjusted) / 2;
		slide.style.marginTop  = top + "px";
		slide.style.marginLeft = "0px";
		slide.style.visibility = "visible";
	} else {
		// Image has more height by ratio than slide, so crop sides
		path         = 1;
		slide.height = heightParent;
		adjusted     = slide.height * (widthImage / heightImage);
		slide.width  = adjusted;
		
		left = (widthParent - adjusted) / 2;
		slide.style.marginLeft = left + "px";
		slide.style.marginTop  = "0px";
		slide.style.visibility = "visible";
	}
	
	debug([
		'path: ' + path,
		'index: ' + index,
		'left: ' + left,
		'top: ' + top,
		'adjusted: ' + adjusted,
		'widthImage: '  + widthImage,
		'widthParent: ' + widthParent, 
		'widthCenter: ' + widthCenter,
		'widthSlide: ' + slide.width,
		'heightImage: '  + heightImage,
		'heightParent: ' + heightParent, 
		'heightCenter: ' + heightCenter,
		'heightSlide: ' + slide.height,
		'ratioParent: ' + ratioParent,
		'ratioImage: ' + ratioImage
	]);
}

function jaxSlideshowNextSlide() {
	
	// Do NOT start flipping slides until the next image in the show has loaded.
	if (jaxSlideshowImageNotYetLoaded(ssIndex + 1)) {
		setTimeout('jaxSlideshowNextSlide()', 1000);
		return;
	}
	
	// Reset footer.
	ssFooter.innerHTML = ssTitles[ssIndex];
	ssFooter.opacity = 0;
	ssFooter.style.opacity = ssFooter.opacity / 100;
	if (window.ActiveXObject) ssFooter.style.filter = "alpha(opacity=" + ssFooter.opacity + ")";
	ssFooter.timer = setTimeout("clearTimeout(ssFooter.timer); ssFooter.timer = setInterval('jaxSlideshowOpacityFooterIncrement()', 50);", ssWaitForFooter);
	
	// ssPrime gets ssSlide's image (redundant on first pass).
	ssPrime.visibility = "hidden";
	ssPrime.src = ssSlide.src;
	jaxSlideshowComputeSizeAndPosition(ssPrime, ssIndex);
	ssPrime.visibility = "visible";
	
	// Increment index; if exceeds array size, loop back to 0.
	ssIndex++;
	if (ssIndex >= ssPaths.length) ssIndex = 0;
	
	// Adjust opacity to invisible.
	ssSlide.opacity = 0;
	ssSlide.style.opacity = 0;
	if (window.ActiveXObject) ssSlide.style.filter = "alpha(opacity=0)";
	
	// Add the new slide to the parent div.
	ssSlide.style.visibility = "hidden";
	ssSlide.src = ssPaths[ssIndex];
	jaxSlideshowComputeSizeAndPosition(ssSlide, ssIndex);
	
	setTimeout(
		'ssSlide.timer = setInterval("jaxSlideshowOpacityImageIncrement()", ssWaitOpacityIncrement);',
		ssWaitForNewSlide
	);
}

function jaxSlideshowOpacityFooterIncrement() {
	// On full opacity start to decrement.
	if (ssFooter.opacity == 100) {
		ssFooter.timer = clearInterval(ssFooter.timer);
		ssFooter.timer = setTimeout("clearTimeout(ssFooter.timer); ssFooter.timer = setInterval('jaxSlideshowOpacityFooterDecrement()', 60);", ssWaitFooterHold);
		return;
	}
	
	ssFooter.style.visibility = "visible";
	ssFooter.opacity += 10;
	ssFooter.style.opacity = ssFooter.opacity / 100;
	if (window.ActiveXObject) ssFooter.style.filter = "alpha(opacity=" + ssFooter.opacity + ")";
}

function jaxSlideshowOpacityFooterDecrement() {
	// On zero opacity clear out the timer.
	if (ssFooter.opacity == 0) {
		ssFooter.timer = clearInterval(ssFooter.timer);
		return;
	}
	
	ssFooter.opacity -= 5;
	ssFooter.style.opacity = ssFooter.opacity / 100;
	if (window.ActiveXObject) ssFooter.style.filter = "alpha(opacity=" + ssFooter.opacity + ")";
}

function jaxSlideshowOpacityImageIncrement() {

	// On full opacity reset slide to next image.
	if (ssSlide.opacity == 100) {
		ssSlide.timer = clearInterval(ssSlide.timer);
		jaxSlideshowNextSlide();
		return;
	}
	
	ssSlide.opacity += 5;
	ssSlide.style.opacity = ssSlide.opacity / 100;
	if (window.ActiveXObject) ssSlide.style.filter = "alpha(opacity=" + ssSlide.opacity + ")";
}

function jaxSlideshowDrawFullsizeGallery(parent){

	var html = '';
	html += "<div id='slideshow_scroll' style='width: 500px; overflow-y: hidden; overflow-x: scroll; margin: auto; border: 1px solid black;'>\n";
	html += "	<div id='slideshow_content'></div>\n";
	html += "</div>\n";
	html += "<div id='slideshow_view' style='width: 500px; margin: auto; padding-top: 20px; border: 1px solid black;'></div>\n";
	parent.innerHTML = html;
	
	// Draw thumbnails in a set of divs.
	var parent = document.getElementById("slideshow_content");
	
	var count = 0;
	var html = "<table id='slideshow_table'><tbody><tr id='slideshow_tr'>\n";
	for (var i = 0; i < ssPaths.length; i++) {
		var id = 'slideshow_thumbnail_' + i;
		
		html += "\t<td";
		html += " class='slideshow_thumbnail'";
		html += ">";
		html += "<img src='" + ssPaths[i] + "'";
		html += " id='" + id + "'";
		html += " onClick='jaxSlideshowShowImage(\"" + id + "\");'";
		html += " height='100'";
		html += ">";
		html += "</td>\n";
	}
	html += "</tr></tbody></table>";
	parent.innerHTML = html + "\t\t";
	
	jaxSlideshowShowImage('slideshow_thumbnail_0');
}

function jaxSlideshowShowImage(id) {
	var src = document.getElementById(id).src;
	document.getElementById('slideshow_view').innerHTML = "<img src='" + src + "' width='500px'>";
}

function findMatchingChildren(id, nodeName){
	var matches = [];
	
	var children = document.getElementById(id).childNodes;
	for (var i = 0; i < children.length; i++) {
		if (children[i].nodeName == nodeName) {
			matches[matches.length] = children[i];
		}
	}
	
	return matches;
}

function jaxSlideshowEnableModal() {
	ssEnableModal = true;
}
function jaxSlideshowHalt(){
	ssSlide.timer = clearInterval(ssSlide.timer);
}
function jaxSlideshowResume(){
	ssSlide.timer = setInterval("jaxSlideshowOpacityImageIncrement()", ssWaitOpacityIncrement);
}

function debug(messageArray){
	if (!document.getElementById('debug')) return;
	var message = "Debug<br/>\n";
	for (var i = 0; i < messageArray.length; i++) {
		message += messageArray[i] + "<br />\n";
	}
	document.getElementById('debug').innerHTML = message;
}
