// slideshow.js
// slideshow functions

/*
SlideShow Constructor.
Call onload with new operator for each instance.
params:
	id --> unique id of wrapper div
	delay --> default delay between slides in MS
	name --> variable that the reference to the object is being put into
	autoplay --> sets weather slideshow starts automaticaly or not (boolean)
*/

function slideShow(id, delay, name, autoplay){
	this.id = id
	this.container = getObject(id)
	// currentdelay changes if there is a delay attribute on the current slide
	this.defaultDelay = delay
	this.currentDelay = delay
	// name is used in timeouts and intervals to reference this object
	this.name = name
	// this collection is all the slides in the slideshow
	this.slides = getChildren(this.container);
	this.slideCount = this.slides.length;
	
	// hide all slides except the first
	for (var i = 0; i < this.slides.length; i++)
	{
		hide(this.slides[i]);
	}
		
		show(this.slides[0]);
	
	// currentslide and nextslide are used internaly to track transitions and playback
	this.currentSlide = 0
	this.nextSlide = 0
	// weather the slideshow is playing or not. this makes it possible to use the playback buttons without the slideshow continuing.
	this.playing = (autoplay)?true:false;
	// timeout is used to cancel slide changes by calling clearTimeout(this.timeout)
	this.timeout = false
	// interval is used to cancel slide transitions by callling clearInterval(this.interval)
	this.interval = false
	
	// METHODS -----------------------------------
	// looks at current slide for delay and transition parameters, sets currentTransition and currentDelay properties.
	this.getSlideParams = slideShowGetSlideParams
	// stops all transitions and displays current slide (returns true if a transition was canceled)
	this.clearActions = slideShowClearActions
	// advances to specific slide (zero based)
	this.showNumber = slideShowShowNumber
	// advances to next slide (pass true value to skip transition)
	this.showNext = slideShowShowNext
	// go to previous slide
	this.showPrevious = slideShowShowPrevious
	// go to first slide
	this.showFirst = slideShowShowFirst
	// go to last slide
	this.showLast = slideShowShowLast
	// stop playback
	this.showStop = slideShowStop
	// start playback
	this.showPlay = slideShowPlay
	// start playback at first slide
	this.showPlayFirst = slideShowPlayFirst
	// set the transition
	// if we support fade, use fade
	// otherwise, flip
	
	if (supportsFade())
	{
		this.defaultTransition = slideShowTransition_fade;
	}
	else
	{
		this.defaultTransition = slideShowTransition_simple;
	}
	
	// starts playback if autoplay set to true
	if(this.playing){
		this.timeout = setTimeout(this.name + '.showNext()', this.currentDelay)
	}	

	// slideshow attatched to containter element, not currently used but good hook for other scripts.
	this.container.slideShow = this
	// container is returned
	return this
}

function slideShowShowNumber(number){
	// stop any activity
	this.clearActions()
	// set new slide to display
	this.nextSlide = number
	// use simple transition to instantly swap the slides
	this.currentTransition = slideShowTransition_fade;
	this.currentTransition()
}
function slideShowShowNext(fast){
	// stop activity and trap weather transition was canceled
	var canceled = this.clearActions()
	// if transition was canceled we delay for next slide or break if not playing.
	if(canceled){
		if(this.playing){
			this.timeout = setTimeout(this.name + '.showNext()', this.currentDelay)
		}
		return
	}
	// otherwise find next slide by testing for end of array
	if(this.currentSlide + 1 < this.slideCount){
		this.nextSlide = this.currentSlide + 1
	}else{
		this.nextSlide = 0
	}
	// use simple if called with fast argument.
	if(fast){
		this.currentTransition = slideShowTransition_fade;
	}
	this.currentTransition()
}
function slideShowShowPrevious(){
	// stop any activity
	this.clearActions()
	// find previous slide by testing for begining of array
	if(this.currentSlide - 1 >= 0){
		this.nextSlide = this.currentSlide - 1
	}else{
		this.nextSlide = this.slideCount - 1
	}
	// use simple transition to instantly switch slides
	this.currentTransition = slideShowTransition_fade;
	this.currentTransition()
}
function slideShowShowFirst(){
		// cancel activity set to 0 and execute simple transition
		this.clearActions()
		this.nextSlide = 0
		this.currentTransition = slideShowTransition_fade;
		this.currentTransition()
}
function slideShowShowLast(){
		// cancel activity set to slideCount -1 and execute simple transition
		this.clearActions()
		this.nextSlide = this.slideCount - 1
		this.currentTransition = slideShowTransition_fade;
		this.currentTransition()
}

function slideShowTransition_simple(){
	// this is the simple transition
		hide(this.slides[this.currentSlide]);
		show(this.slides[this.nextSlide]);
	// transition complete so we set currentsSlide to nextSlide
	this.currentSlide = this.nextSlide
	// test currentSlide for params.
	this.getSlideParams()
	// if play enabled timeout for next slide
	if(this.playing){
		this.timeout = setTimeout(this.name + '.showNext()', this.currentDelay)
	}
}
function slideShowTransition_fade(iteration){
	// this is the fading transition
	// sets increment for opacity (1 - 100)
	var step = 15
	// sets delay in ms between frames of animation
	var delay = 3
	// this function calls itself recursively, if iteration param is not set it is first run.
	if(iteration != true){
		// nextslide is layered above other slides
		setStyle(this.slides[this.nextSlide], "zIndex", 1);
		// nextslide opacity is set to 0
		setOpacity(this.slides[this.nextSlide], 0)
		// nextslide visibility set to visible
		show(this.slides[this.nextSlide]);
		// set up interval to call this function with delay above
		this.interval = setInterval(this.name + '.currentTransition(true)', delay)
		return
	}else{
		// this is executed when looping
		// op is a property of the element created by the setOpacity function for compatibility reasons.
		var op = this.slides[this.nextSlide].op
		// increment op
		op += step
		// if 99 or more we finish the transition
		if(op >= 99){
			 // set opacity to 99 because Firefox flickers if you go to 100
			 setOpacity(this.slides[this.nextSlide], 99)
			 // hide old current slide
			 hide(this.slides[this.currentSlide]);
			 // push new slide back to 0 index
			 setStyle(this.slides[this.nextSlide], "zIndex", 0);
			 // cancel loop
			 if(this.interval){
			 	 clearInterval(this.interval)
			 	 this.interval = false
			 }
		}else{
			// otherwise we set the opacity and loop again
			setOpacity(this.slides[this.nextSlide], op)
			return
		}
	}
	// transition complete so we set currentsSlide to nextSlide
	this.currentSlide = this.nextSlide
	// test currentSlide for params.
	this.getSlideParams()
	// if play enabled timeout for next slide
	if(this.playing){
		this.timeout = setTimeout(this.name + '.showNext()', this.currentDelay)
	}
}


// checks currentslide for delay and transition attributes.
function slideShowGetSlideParams(){
	var slide = this.slides[this.currentSlide];
	
	if(slide.getAttribute && slide.getAttribute('delay')){
		this.currentDelay = slide.getAttribute('delay') * 1000;
	}
	else{
		this.currentDelay = this.defaultDelay;
	}
	
	
	this.currentTransition = this.defaultTransition
}


// sets all slides to default position visibility and opacity.
// returns true if there was a transition in progress.
// return value used by showNext to keep from skipping slides.
function slideShowClearActions(){
	// return value
	var canceled = false
	// if interval not false we are in a transition
	if(this.interval){
		// transition is canceled and slide advanced
		clearInterval(this.interval)
		this.interval = false
		this.currentSlide = this.nextSlide
		// return value set true
		canceled = true
	}
	// loop through slides and set to default styles
	for(i=0;i<this.slides.length;i++){
		var slide = this.slides[i]
		// if currentslide show, otherwise hide.
		if(i == this.currentSlide){
			show(slide);
		}else{
			hide(slide);
		}
		// test op before setting to reduce ns funniness
		if (this.defaultTransition == slideShowTransition_fade)
		{
			if(slide.op != 99)	setOpacity(slide, 99);
			setStyle(slide, "zIndex", 0);
		}
	}
	// if timeout not false a slide change is in the works, so we cancel it.
	if(this.timeout){
		clearTimeout(this.timeout)
		this.timeout = false
	}
	// test currentSlide for delay and transition attributes
	this.getSlideParams()
	return canceled
}
// sets playing to true and starts animation if it wasn't already going.
function slideShowPlay(){
	this.playing = true
	if(this.interval){
		return
	}else{
		this.clearActions()
		this.showNext()
	}
}

function slideShowPlayFirst(){
	this.playing = true
	if(this.interval){
		return
	}else{
		this.clearActions()
		this.showFirst()
	}
}

// sets playing to false and stops animation
function slideShowStop(){
	this.playing = false
	this.clearActions()
}

// sets opacity for elements. created because netscape and ie have different methods of applying opacity.
// note that filter has to be set in stylesheet for the element that will use it.
function setOpacity(elm, opacity){
		elm.op = opacity;
		var nn6= (document.getElementById && !document.all)?true:false;
		// added in a check for opera
		// var ie5= (document.all && document.getElementById && !window.opera && elm.filters && elm.filters.alpha && supportsOpacity(elm))?true:false;
		var ie5= (document.all && document.getElementById && !window.opera)?true:false;
		if(ie5){
			// due to an odd ie bug, things get weird if opacity is less than 5			
			if (opacity < 15 )
				opacity = 15;
			var opacityString = "alpha(opacity=" + opacity + ")";
			elm.style.filter = opacityString;
		}
		if(nn6){
			elm.style.MozOpacity = opacity / 100
		}
	}

function supportsFade(elm)
{
		var nn6= (document.getElementById && !document.all)?true:false;
		// added in a check for opera
		// var ie5= (document.all && document.getElementById && !window.opera && elm.filters && elm.filters.alpha && supportsOpacity(elm))?true:false;
		var ie5= (document.all && document.getElementById && !window.opera)?true:false;
		
		return (nn6 || ie5);
}
