var Jsslideshow = new Object();

Jsslideshow.init = function(prefix, msec, max)
// Initialises a slide show - you only need to call this if you want to have more than one on a page, or if you need to change the id-prefix of the elements
{
	this.prefix = prefix ? prefix : "Jsslideshow";
	this.default_interval = msec ? parseInt(msec) : 3500;
	this.selected = 0;
	this.max = max ? parseInt(max) : 12;
	
	this.fadeInDelay = 200; // Setting this to 0 will suppress fade out. Positive values will issue fade in this amount of milliseconds after starting fade out.
	this.opacitySteps = 10; // 5 or 10 steps
	this.fadeInTime = 200; // Total time to fade in in milliseconds
	this.fadeOutTime = 400; // Total time to fade out in milliseconds
}

Jsslideshow.getElem = function(i)
{
	var elem = document.getElementById(this.prefix + ":" + i);
	return elem ? elem : false;
}

Jsslideshow.getVisible = function()
{
	for (var i = 0; i <= this.max; i++)
	{
		var elem = this.getElem(i);
		if (elem && !Typic.hasClassName(elem, "hidden"))
		{
			return i;
		}
	}
}

Jsslideshow.autoStart = function(msec)
// Starts the slideshow
// msec (optional) is the interval in milliseconds. Defaults to the value specified at the top
// NOTE: If the slideshow is already started, it will essentially continue, but with the new msec interval
{
	if (this.timer)
		this.autoStop();

	if (!msec)
		msec = this.default_interval;
		
	this.timer = setInterval(this.prefix + ".showNext()", msec);
}

Jsslideshow.autoStop = function()
// Stops the slideshow
{
	this.timer = clearInterval(this.timer);
}

Jsslideshow.autoToggle = function()
// Starts or stops the slideshow
{
	if (this.timer)
		this.autoStop();
	else
		this.autoStart();
}

Jsslideshow.showPrev = function(i)
// Shows the previous slide
{
	if (i == undefined)
		i = this.selected;
	else if (i == this.selected)
		return;
		
	if (i == 0)
		i = this.max;
	else
		i--;	
	
	if (!this.getElem(i))
		setTimeout(this.prefix + ".showPrev("+i+")", 10); 
	else
		this.show(i);
}

Jsslideshow.showNext = function(i)
// Shows the next slide
// Rewinds to the beginning when reaching the end
{
	if (i == undefined)
	{
		if (this.selected == undefined)
			this.selected = this.getVisible();
		i = this.selected;
	}
	else if (i == this.selected)
		return;
		
	if (i == this.max)
		i = 0;
	else
		i++;

	if (!this.getElem(i))
		setTimeout(this.prefix + ".showNext("+i+")", 10); 
	else
		this.show(i);
}

Jsslideshow.show = function(i)
// Shows a specific slide (fades in)
{
	if (i == this.selected)
		return;
	var elem = this.getElem(i);
	if (elem)
	{	
		if (this.fadeInDelay > 0)
			this.fadeOut(this.selected);
		setTimeout(this.prefix + ".fadeIn("+i+")", this.fadeInDelay);
	}
}

Jsslideshow.hide = function(i)
// Hides a specific slide (immediately)
{
	var elem = this.getElem(i);
	if (elem)
	{	
		if (!Typic.hasClassName(elem, "hidden"))
			Typic.addClassName(elem, "hidden");
	}
}

Jsslideshow.fadeIn = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		var opacity_match = elem.className.match(/opacity([^\s]+)/i);

		if (!opacity_match) // Starting fade in
		{
			Typic.addClassName(elem, "opacity0");
			Typic.removeClassName(elem, "hidden");
			Typic.addClassName(elem, "on_top");
			this.fadeIn(i);
			return;
		}

		var opacity_class = opacity_match[0];
		var opacity = parseInt(opacity_match[1]);

		if (opacity > 90)	// Ending fade in
		{
			this.hide(this.selected);
	 		this.selected = i;
	 		Typic.removeClassName(elem, opacity_class);
	 		Typic.removeClassName(elem, "on_top");
			return;
		}

		opacity = opacity + parseInt(100 / this.opacitySteps);
		Typic.addClassName(elem, "opacity" + opacity);
		Typic.removeClassName(elem, opacity_class);

		setTimeout(this.prefix + ".fadeIn("+i+")", parseInt(this.fadeInTime / this.opacitySteps));
	}			 	
}

Jsslideshow.fadeOut = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		var opacity_match = elem.className.match(/opacity([^\s]+)/i);

		if (!opacity_match) // Starting fade out
		{
			Typic.addClassName(elem, "opacity100");
			this.fadeOut(i);
			return;
		}

		var opacity_class = opacity_match[0];
		var opacity = parseInt(opacity_match[1]);
		
		if (opacity < 10)
		{
			Typic.removeClassName(elem, opacity_class);
			this.hide(i);
			return;
		}

		opacity = opacity - parseInt(100 / this.opacitySteps);
		Typic.addClassName(elem, "opacity" + opacity);
		Typic.removeClassName(elem, opacity_class);

		setTimeout(this.prefix + ".fadeOut("+i+")", parseInt(this.fadeOutTime / this.opacitySteps));
	}			 	
}

function cloneObject(what)
{
    for (i in what) {
        if (typeof what[i] == 'object') {
            this[i] = new cloneObject(what[i]);
        }
        else
            this[i] = what[i];
    }
}

Jsslideshow.init();

/* .... TYPIC OBJECT ... */

Typic = new Object();

Typic.elementExistsInStringList = function(element, stringList, separator)
{
	// separator might need regexp escaping first...
	return stringList.match(new RegExp("(^|"+separator+")" + element + "("+separator+"|$)", "i"));
}
Typic.hasClassName = function(elem, className)
{
	return elem.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)", "i"));
}
Typic.addClassName = function(elem, className)
{
	elem.className = elem.className + " " + className;
}
Typic.removeClassName = function(elem, className)
{
	elem.className = elem.className.replace(new RegExp("(^|\\s)(" + className + ")(\\s|$)", "gi"), "$1$3");
}

Typic.toggleClassName = function(elem, className)
{
	if (Typic.hasClassName(elem, className))
		Typic.removeClassName(elem, className);
	else
		Typic.addClassName(elem, className);
}

Typic.addMethods = function(elem)
{
	elem.addClassName = function()
	{
		Typic.addClassName(this, arguments[0]);
	}
	elem.removeClassName = function()
	{
		Typic.removeClassName(this, arguments[0]);
	}
	elem.hasClassName = function()
	{
		return Typic.hasClassName(this, arguments[0]);
	}
}

Typic.mouseover_init = function(elem)
{
	if(!/MSIE (5|6)/.test(navigator.userAgent)) 
	// No need to add mouseover events. Browser probably already understands :hover
	{
		elem.onmouseover = null;
		return;
	}

	elem.onmouseover = function() {Typic.addClassName(this, 'mouseover');}
	elem.onmouseout = function() {Typic.removeClassName(this, 'mouseover');}
}